diff options
375 files changed, 11546 insertions, 7884 deletions
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt index b41397d..033a3f3 100644 --- a/Documentation/powerpc/booting-without-of.txt +++ b/Documentation/powerpc/booting-without-of.txt @@ -39,7 +39,7 @@ and property data. The old style variable alignment would make it impossible to do "simple" insertion of properties using - memove (thanks Milton for + memmove (thanks Milton for noticing). Updated kernel patch as well - Correct a few more alignment constraints - Add a chapter about the device-tree @@ -55,7 +55,7 @@ ToDo: - Add some definitions of interrupt tree (simple/complex) - - Add some definitions for pci host bridges + - Add some definitions for PCI host bridges - Add some common address format examples - Add definitions for standard properties and "compatible" names for cells that are not already defined by the existing @@ -114,7 +114,7 @@ it with special cases. forth words isn't required), you can enter the kernel with: r5 : OF callback pointer as defined by IEEE 1275 - bindings to powerpc. Only the 32 bit client interface + bindings to powerpc. Only the 32-bit client interface is currently supported r3, r4 : address & length of an initrd if any or 0 @@ -194,7 +194,7 @@ it with special cases. for this is to keep kernels on embedded systems small and efficient; part of this is due to the fact the code is already that way. In the future, a kernel may support multiple platforms, but only if the - platforms feature the same core architectire. A single kernel build + platforms feature the same core architecture. A single kernel build cannot support both configurations with Book E and configurations with classic Powerpc architectures. @@ -215,7 +215,7 @@ of the boot sequences.... someone speak up if this is wrong! enable another config option to select the specific board supported. -NOTE: If ben doesn't merge the setup files, may need to change this to +NOTE: If Ben doesn't merge the setup files, may need to change this to point to setup_32.c @@ -256,7 +256,7 @@ struct boot_param_header { u32 off_dt_struct; /* offset to structure */ u32 off_dt_strings; /* offset to strings */ u32 off_mem_rsvmap; /* offset to memory reserve map -*/ + */ u32 version; /* format version */ u32 last_comp_version; /* last compatible version */ @@ -265,6 +265,9 @@ struct boot_param_header { booting on */ /* version 3 fields below */ u32 size_dt_strings; /* size of the strings block */ + + /* version 17 fields below */ + u32 size_dt_struct; /* size of the DT structure block */ }; Along with the constants: @@ -273,7 +276,7 @@ struct boot_param_header { #define OF_DT_HEADER 0xd00dfeed /* 4: version, 4: total size */ #define OF_DT_BEGIN_NODE 0x1 /* Start node: full name -*/ + */ #define OF_DT_END_NODE 0x2 /* End node */ #define OF_DT_PROP 0x3 /* Property: name off, size, content */ @@ -310,9 +313,8 @@ struct boot_param_header { - off_mem_rsvmap This is an offset from the beginning of the header to the start - of the reserved memory map. This map is a list of pairs of 64 + of the reserved memory map. This map is a list of pairs of 64- bit integers. Each pair is a physical address and a size. The - list is terminated by an entry of size 0. This map provides the kernel with a list of physical memory areas that are "reserved" and thus not to be used for memory allocations, especially during @@ -325,7 +327,7 @@ struct boot_param_header { contain _at least_ this DT block itself (header,total_size). If you are passing an initrd to the kernel, you should reserve it as well. You do not need to reserve the kernel image itself. The map - should be 64 bit aligned. + should be 64-bit aligned. - version @@ -335,10 +337,13 @@ struct boot_param_header { to reallocate it easily at boot and free up the unused flattened structure after expansion. Version 16 introduces a new more "compact" format for the tree itself that is however not backward - compatible. You should always generate a structure of the highest - version defined at the time of your implementation. Currently - that is version 16, unless you explicitly aim at being backward - compatible. + compatible. Version 17 adds an additional field, size_dt_struct, + allowing it to be reallocated or moved more easily (this is + particularly useful for bootloaders which need to make + adjustments to a device tree based on probed information). You + should always generate a structure of the highest version defined + at the time of your implementation. Currently that is version 17, + unless you explicitly aim at being backward compatible. - last_comp_version @@ -347,7 +352,7 @@ struct boot_param_header { is backward compatible with version 1 (that is, a kernel build for version 1 will be able to boot with a version 2 format). You should put a 1 in this field if you generate a device tree of - version 1 to 3, or 0x10 if you generate a tree of version 0x10 + version 1 to 3, or 16 if you generate a tree of version 16 or 17 using the new unit name format. - boot_cpuid_phys @@ -360,6 +365,17 @@ struct boot_param_header { point (see further chapters for more informations on the required device-tree contents) + - size_dt_strings + + This field only exists on version 3 and later headers. It + gives the size of the "strings" section of the device tree (which + starts at the offset given by off_dt_strings). + + - size_dt_struct + + This field only exists on version 17 and later headers. It gives + the size of the "structure" section of the device tree (which + starts at the offset given by off_dt_struct). So the typical layout of a DT block (though the various parts don't need to be in that order) looks like this (addresses go from top to @@ -417,7 +433,7 @@ root node who has no parent. A node has 2 names. The actual node name is generally contained in a property of type "name" in the node property list whose value is a zero terminated string and is mandatory for version 1 to 3 of the -format definition (as it is in Open Firmware). Version 0x10 makes it +format definition (as it is in Open Firmware). Version 16 makes it optional as it can generate it from the unit name defined below. There is also a "unit name" that is used to differentiate nodes with @@ -461,7 +477,7 @@ referencing another node via "phandle" is when laying out the interrupt tree which will be described in a further version of this document. -This "linux, phandle" property is a 32 bit value that uniquely +This "linux, phandle" property is a 32-bit value that uniquely identifies a node. You are free to use whatever values or system of values, internal pointers, or whatever to generate these, the only requirement is that every node for which you provide that property has @@ -471,7 +487,7 @@ Here is an example of a simple device-tree. In this example, an "o" designates a node followed by the node unit name. Properties are presented with their name followed by their content. "content" represents an ASCII string (zero terminated) value, while <content> -represents a 32 bit hexadecimal value. The various nodes in this +represents a 32-bit hexadecimal value. The various nodes in this example will be discussed in a later chapter. At this point, it is only meant to give you a idea of what a device-tree looks like. I have purposefully kept the "name" and "linux,phandle" properties which @@ -543,15 +559,15 @@ Here's the basic structure of a single node: * [align gap to next 4 bytes boundary] * for each property: * token OF_DT_PROP (that is 0x00000003) - * 32 bit value of property value size in bytes (or 0 of no - * value) - * 32 bit value of offset in string block of property name + * 32-bit value of property value size in bytes (or 0 if no + value) + * 32-bit value of offset in string block of property name * property value data if any * [align gap to next 4 bytes boundary] * [child nodes if any] * token OF_DT_END_NODE (that is 0x00000002) -So the node content can be summarised as a start token, a full path, +So the node content can be summarized as a start token, a full path, a list of properties, a list of child nodes, and an end token. Every child node is a full node structure itself as defined above. @@ -583,7 +599,7 @@ provide those properties yourself. ---------------------------------------------- The general rule is documented in the various Open Firmware -documentations. If you chose to describe a bus with the device-tree +documentations. If you choose to describe a bus with the device-tree and there exist an OF bus binding, then you should follow the specification. However, the kernel does not require every single device or bus to be described by the device tree. @@ -596,9 +612,9 @@ those properties defining addresses format for devices directly mapped on the processor bus. Those 2 properties define 'cells' for representing an address and a -size. A "cell" is a 32 bit number. For example, if both contain 2 +size. A "cell" is a 32-bit number. For example, if both contain 2 like the example tree given above, then an address and a size are both -composed of 2 cells, and each is a 64 bit number (cells are +composed of 2 cells, and each is a 64-bit number (cells are concatenated and expected to be in big endian format). Another example is the way Apple firmware defines them, with 2 cells for an address and one cell for a size. Most 32-bit implementations should define @@ -632,7 +648,7 @@ prom_parse.c file of the recent kernels for your bus type. The "reg" property only defines addresses and sizes (if #size-cells is non-0) within a given bus. In order to translate addresses upward -(that is into parent bus addresses, and possibly into cpu physical +(that is into parent bus addresses, and possibly into CPU physical addresses), all busses must contain a "ranges" property. If the "ranges" property is missing at a given level, it's assumed that translation isn't possible. The format of the "ranges" property for a @@ -648,9 +664,9 @@ example, for a PCI host controller, that would be a CPU address. For a PCI<->ISA bridge, that would be a PCI address. It defines the base address in the parent bus where the beginning of that range is mapped. -For a new 64 bit powerpc board, I recommend either the 2/2 format or +For a new 64-bit powerpc board, I recommend either the 2/2 format or Apple's 2/1 format which is slightly more compact since sizes usually -fit in a single 32 bit word. New 32 bit powerpc boards should use a +fit in a single 32-bit word. New 32-bit powerpc boards should use a 1/1 format, unless the processor supports physical addresses greater than 32-bits, in which case a 2/1 format is recommended. @@ -764,7 +780,7 @@ address which can extend beyond that limit. Required properties: - device_type : has to be "cpu" - - reg : This is the physical cpu number, it's a single 32 bit cell + - reg : This is the physical CPU number, it's a single 32-bit cell and is also used as-is as the unit number for constructing the unit name in the full path. For example, with 2 CPUs, you would have the full path: @@ -785,7 +801,7 @@ address which can extend beyond that limit. the kernel timebase/decrementer calibration based on this value. - clock-frequency : a cell indicating the CPU core clock frequency - in Hz. A new property will be defined for 64 bit values, but if + in Hz. A new property will be defined for 64-bit values, but if your frequency is < 4Ghz, one cell is enough. Here as well as for the above, the common code doesn't use that property, but you are welcome to re-use the pSeries or Maple one. A future @@ -832,8 +848,7 @@ address which can extend beyond that limit. This node is a bit "special". Normally, that's where open firmware puts some variable environment information, like the arguments, or - phandle pointers to nodes like the main interrupt controller, or the - default input/output devices. + the default input/output devices. This specification makes a few of these mandatory, but also defines some linux-specific properties that would be normally constructed by @@ -853,14 +868,14 @@ address which can extend beyond that limit. that the kernel tries to find out the default console and has knowledge of various types like 8250 serial ports. You may want to extend this function to add your own. - - interrupt-controller : This is one cell containing a phandle - value that matches the "linux,phandle" property of your main - interrupt controller node. May be used for interrupt routing. - Note that u-boot creates and fills in the chosen node for platforms that use it. + (Note: a practice that is now obsolete was to include a property + under /chosen called interrupt-controller which had a phandle value + that pointed to the main interrupt controller) + f) the /soc<SOCname> node This node is used to represent a system-on-a-chip (SOC) and must be @@ -908,8 +923,7 @@ address which can extend beyond that limit. The SOC node may contain child nodes for each SOC device that the platform uses. Nodes should not be created for devices which exist on the SOC but are not used by a particular platform. See chapter VI - for more information on how to specify devices that are part of an -SOC. + for more information on how to specify devices that are part of a SOC. Example SOC node for the MPC8540: @@ -972,7 +986,7 @@ The syntax of the dtc tool is [-o output-filename] [-V output_version] input_filename -The "output_version" defines what versio of the "blob" format will be +The "output_version" defines what version of the "blob" format will be generated. Supported versions are 1,2,3 and 16. The default is currently version 3 but that may change in the future to version 16. @@ -994,12 +1008,12 @@ supported currently at the toplevel. */ property2 = <1234abcd>; /* define a property containing a - * numerical 32 bits value (hexadecimal) + * numerical 32-bit value (hexadecimal) */ property3 = <12345678 12345678 deadbeef>; /* define a property containing 3 - * numerical 32 bits values (cells) in + * numerical 32-bit values (cells) in * hexadecimal */ property4 = [0a 0b 0c 0d de ea ad be ef]; @@ -1068,7 +1082,7 @@ while all this has been defined and implemented. its usage in early_init_devtree(), and the corresponding various early_init_dt_scan_*() callbacks. That code can be re-used in a GPL bootloader, and as the author of that code, I would be happy - to discuss possible free licencing to any vendor who wishes to + to discuss possible free licensing to any vendor who wishes to integrate all or part of this code into a non-GPL bootloader. @@ -1077,7 +1091,7 @@ VI - System-on-a-chip devices and nodes ======================================= Many companies are now starting to develop system-on-a-chip -processors, where the processor core (cpu) and many peripheral devices +processors, where the processor core (CPU) and many peripheral devices exist on a single piece of silicon. For these SOCs, an SOC node should be used that defines child nodes for the devices that make up the SOC. While platforms are not required to use this model in @@ -1109,42 +1123,7 @@ See appendix A for an example partial SOC node definition for the MPC8540. -2) Specifying interrupt information for SOC devices ---------------------------------------------------- - -Each device that is part of an SOC and which generates interrupts -should have the following properties: - - - interrupt-parent : contains the phandle of the interrupt - controller which handles interrupts for this device - - interrupts : a list of tuples representing the interrupt - number and the interrupt sense and level for each interrupt - for this device. - -This information is used by the kernel to build the interrupt table -for the interrupt controllers in the system. - -Sense and level information should be encoded as follows: - - Devices connected to openPIC-compatible controllers should encode - sense and polarity as follows: - - 0 = low to high edge sensitive type enabled - 1 = active low level sensitive type enabled - 2 = active high level sensitive type enabled - 3 = high to low edge sensitive type enabled - - ISA PIC interrupt controllers should adhere to the ISA PIC - encodings listed below: - - 0 = active low level sensitive type enabled - 1 = active high level sensitive type enabled - 2 = high to low edge sensitive type enabled - 3 = low to high edge sensitive type enabled - - - -3) Representing devices without a current OF specification +2) Representing devices without a current OF specification ---------------------------------------------------------- Currently, there are many devices on SOCs that do not have a standard @@ -1201,6 +1180,13 @@ platforms are moved over to use the flattened-device-tree model. - phy-handle : The phandle for the PHY connected to this ethernet controller. + Recommended properties: + + - linux,network-index : This is the intended "index" of this + network device. This is used by the bootwrapper to interpret + MAC addresses passed by the firmware when no information other + than indices is available to associate an address with a device. + Example: ethernet@24000 { @@ -1312,10 +1298,10 @@ platforms are moved over to use the flattened-device-tree model. and additions : Required properties : - - compatible : Should be "fsl-usb2-mph" for multi port host usb - controllers, or "fsl-usb2-dr" for dual role usb controllers - - phy_type : For multi port host usb controllers, should be one of - "ulpi", or "serial". For dual role usb controllers, should be + - compatible : Should be "fsl-usb2-mph" for multi port host USB + controllers, or "fsl-usb2-dr" for dual role USB controllers + - phy_type : For multi port host USB controllers, should be one of + "ulpi", or "serial". For dual role USB controllers, should be one of "ulpi", "utmi", "utmi_wide", or "serial". - reg : Offset and length of the register set for the device - port0 : boolean; if defined, indicates port0 is connected for @@ -1339,7 +1325,7 @@ platforms are moved over to use the flattened-device-tree model. - interrupt-parent : the phandle for the interrupt controller that services interrupts for this device. - Example multi port host usb controller device node : + Example multi port host USB controller device node : usb@22000 { device_type = "usb"; compatible = "fsl-usb2-mph"; @@ -1353,7 +1339,7 @@ platforms are moved over to use the flattened-device-tree model. port1; }; - Example dual role usb controller device node : + Example dual role USB controller device node : usb@23000 { device_type = "usb"; compatible = "fsl-usb2-dr"; @@ -1387,7 +1373,7 @@ platforms are moved over to use the flattened-device-tree model. - channel-fifo-len : An integer representing the number of descriptor pointers each channel fetch fifo can hold. - exec-units-mask : The bitmask representing what execution units - (EUs) are available. It's a single 32 bit cell. EU information + (EUs) are available. It's a single 32-bit cell. EU information should be encoded following the SEC's Descriptor Header Dword EU_SEL0 field documentation, i.e. as follows: @@ -1403,7 +1389,7 @@ platforms are moved over to use the flattened-device-tree model. bits 8 through 31 are reserved for future SEC EUs. - descriptor-types-mask : The bitmask representing what descriptors - are available. It's a single 32 bit cell. Descriptor type + are available. It's a single 32-bit cell. Descriptor type information should be encoded following the SEC's Descriptor Header Dword DESC_TYPE field documentation, i.e. as follows: @@ -1492,7 +1478,7 @@ platforms are moved over to use the flattened-device-tree model. Required properties: - device_type : should be "spi". - compatible : should be "fsl_spi". - - mode : the spi operation mode, it can be "cpu" or "qe". + - mode : the SPI operation mode, it can be "cpu" or "qe". - reg : Offset and length of the register set for the device - interrupts : <a b> where a is the interrupt number and b is a field that represents an encoding of the sense and level @@ -1569,6 +1555,12 @@ platforms are moved over to use the flattened-device-tree model. - mac-address : list of bytes representing the ethernet address. - phy-handle : The phandle for the PHY connected to this controller. + Recommended properties: + - linux,network-index : This is the intended "index" of this + network device. This is used by the bootwrapper to interpret + MAC addresses passed by the firmware when no information other + than indices is available to associate an address with a device. + Example: ucc@2000 { device_type = "network"; @@ -1712,7 +1704,7 @@ platforms are moved over to use the flattened-device-tree model. - partitions : Several pairs of 32-bit values where the first value is partition's offset from the start of the device and the second one is partition size in bytes with LSB used to signify a read only - partition (so, the parition size should always be an even number). + partition (so, the partition size should always be an even number). - partition-names : The list of concatenated zero terminated strings representing the partition names. - probe-type : The type of probe which should be done for the chip @@ -1733,6 +1725,92 @@ platforms are moved over to use the flattened-device-tree model. More devices will be defined as this spec matures. +VII - Specifying interrupt information for devices +=================================================== + +The device tree represents the busses and devices of a hardware +system in a form similar to the physical bus topology of the +hardware. + +In addition, a logical 'interrupt tree' exists which represents the +hierarchy and routing of interrupts in the hardware. + +The interrupt tree model is fully described in the +document "Open Firmware Recommended Practice: Interrupt +Mapping Version 0.9". The document is available at: +<http://playground.sun.com/1275/practice>. + +1) interrupts property +---------------------- + +Devices that generate interrupts to a single interrupt controller +should use the conventional OF representation described in the +OF interrupt mapping documentation. + +Each device which generates interrupts must have an 'interrupt' +property. The interrupt property value is an arbitrary number of +of 'interrupt specifier' values which describe the interrupt or +interrupts for the device. + +The encoding of an interrupt specifier is determined by the +interrupt domain in which the device is located in the +interrupt tree. The root of an interrupt domain specifies in +its #interrupt-cells property the number of 32-bit cells +required to encode an interrupt specifier. See the OF interrupt +mapping documentation for a detailed description of domains. + +For example, the binding for the OpenPIC interrupt controller +specifies an #interrupt-cells value of 2 to encode the interrupt +number and level/sense information. All interrupt children in an +OpenPIC interrupt domain use 2 cells per interrupt in their interrupts +property. + +The PCI bus binding specifies a #interrupt-cell value of 1 to encode +which interrupt pin (INTA,INTB,INTC,INTD) is used. + +2) interrupt-parent property +---------------------------- + +The interrupt-parent property is specified to define an explicit +link between a device node and its interrupt parent in +the interrupt tree. The value of interrupt-parent is the +phandle of the parent node. + +If the interrupt-parent property is not defined for a node, it's +interrupt parent is assumed to be an ancestor in the node's +_device tree_ hierarchy. + +3) OpenPIC Interrupt Controllers +-------------------------------- + +OpenPIC interrupt controllers require 2 cells to encode +interrupt information. The first cell defines the interrupt +number. The second cell defines the sense and level +information. + +Sense and level information should be encoded as follows: + + 0 = low to high edge sensitive type enabled + 1 = active low level sensitive type enabled + 2 = active high level sensitive type enabled + 3 = high to low edge sensitive type enabled + +4) ISA Interrupt Controllers +---------------------------- + +ISA PIC interrupt controllers require 2 cells to encode +interrupt information. The first cell defines the interrupt +number. The second cell defines the sense and level +information. + +ISA PIC interrupt controllers should adhere to the ISA PIC +encodings listed below: + + 0 = active low level sensitive type enabled + 1 = active high level sensitive type enabled + 2 = high to low edge sensitive type enabled + 3 = low to high edge sensitive type enabled + Appendix A - Sample SOC node for MPC8540 ======================================== diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 6dfbd52..a54a9a2e 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -11,6 +11,11 @@ config PPC64 This option selects whether a 32-bit or a 64-bit kernel will be built. +config PPC_PM_NEEDS_RTC_LIB + bool + select RTC_LIB + default y if PM + config PPC32 bool default y if !PPC64 @@ -89,7 +94,7 @@ config SCHED_NO_NO_OMIT_FRAME_POINTER config ARCH_MAY_HAVE_PC_FDC bool - default y + default !PPC_PSERIES || PCI config PPC_OF def_bool y @@ -157,17 +162,20 @@ config PPC_83xx select FSL_SOC select 83xx select PPC_FPU + select WANT_DEVICE_TREE config PPC_85xx bool "Freescale 85xx" select E500 select FSL_SOC select 85xx + select WANT_DEVICE_TREE config PPC_86xx bool "Freescale 86xx" select 6xx select FSL_SOC + select FSL_PCIE select PPC_FPU select ALTIVEC help @@ -186,7 +194,6 @@ config 44x bool "AMCC 44x" select PPC_DCR_NATIVE - config E200 bool "Freescale e200" @@ -367,394 +374,7 @@ endmenu source "init/Kconfig" -menu "Platform support" - depends on PPC64 || CLASSIC32 - -choice - prompt "Machine type" - default PPC_MULTIPLATFORM - -config PPC_MULTIPLATFORM - bool "Generic desktop/server/laptop" - help - Select this option if configuring for an IBM pSeries or - RS/6000 machine, an Apple machine, or a PReP, CHRP, - Maple or Cell-based machine. - -config EMBEDDED6xx - bool "Embedded 6xx/7xx/7xxx-based board" - depends on PPC32 && (BROKEN||BROKEN_ON_SMP) - -config APUS - bool "Amiga-APUS" - depends on PPC32 && BROKEN - help - Select APUS if configuring for a PowerUP Amiga. - More information is available at: - <http://linux-apus.sourceforge.net/>. -endchoice - -config QUICC_ENGINE - bool - depends on PPC_MPC836x || PPC_MPC832x - default y - help - The QUICC Engine (QE) is a new generation of communications - coprocessors on Freescale embedded CPUs (akin to CPM in older chips). - Selecting this option means that you wish to build a kernel - for a machine with a QE coprocessor. - -config PPC_PSERIES - depends on PPC_MULTIPLATFORM && PPC64 - bool "IBM pSeries & new (POWER5-based) iSeries" - select MPIC - select PPC_I8259 - select PPC_RTAS - select RTAS_ERROR_LOGGING - select PPC_UDBG_16550 - select PPC_NATIVE - default y - -config PPC_ISERIES - bool "IBM Legacy iSeries" - depends on PPC_MULTIPLATFORM && PPC64 - select PPC_INDIRECT_IO - -config PPC_CHRP - bool "Common Hardware Reference Platform (CHRP) based machines" - depends on PPC_MULTIPLATFORM && PPC32 - select MPIC - select PPC_I8259 - select PPC_INDIRECT_PCI - select PPC_RTAS - select PPC_MPC106 - select PPC_UDBG_16550 - select PPC_NATIVE - default y - -config PPC_MPC52xx - bool - default n - -config PPC_MPC5200 - bool - select PPC_MPC52xx - default n - -config PPC_MPC5200_BUGFIX - bool "MPC5200 (L25R) bugfix support" - depends on PPC_MPC5200 - default n - help - Enable workarounds for original MPC5200 errata. This is not required - for MPC5200B based boards. - - It is safe to say 'Y' here - -config PPC_EFIKA - bool "bPlan Efika 5k2. MPC5200B based computer" - depends on PPC_MULTIPLATFORM && PPC32 - select PPC_RTAS - select RTAS_PROC - select PPC_MPC52xx - select PPC_NATIVE - default n - -config PPC_LITE5200 - bool "Freescale Lite5200 Eval Board" - depends on PPC_MULTIPLATFORM && PPC32 - select PPC_MPC5200 - default n - -config PPC_PMAC - bool "Apple PowerMac based machines" - depends on PPC_MULTIPLATFORM - select MPIC - select PPC_INDIRECT_PCI if PPC32 - select PPC_MPC106 if PPC32 - select PPC_NATIVE - default y - -config PPC_PMAC64 - bool - depends on PPC_PMAC && POWER4 - select MPIC - select U3_DART - select MPIC_BROKEN_U3 - select GENERIC_TBSYNC - select PPC_970_NAP - default y - -config PPC_PREP - bool "PowerPC Reference Platform (PReP) based machines" - depends on PPC_MULTIPLATFORM && PPC32 && BROKEN - select MPIC - select PPC_I8259 - select PPC_INDIRECT_PCI - select PPC_UDBG_16550 - select PPC_NATIVE - default n - -config PPC_MAPLE - depends on PPC_MULTIPLATFORM && PPC64 - bool "Maple 970FX Evaluation Board" - select MPIC - select U3_DART - select MPIC_BROKEN_U3 - select GENERIC_TBSYNC - select PPC_UDBG_16550 - select PPC_970_NAP - select PPC_NATIVE - select PPC_RTAS - select MMIO_NVRAM - select ATA_NONSTANDARD if ATA - default n - help - This option enables support for the Maple 970FX Evaluation Board. - For more information, refer to <http://www.970eval.com> - -config PPC_PASEMI - depends on PPC_MULTIPLATFORM && PPC64 - bool "PA Semi SoC-based platforms" - default n - select MPIC - select PPC_UDBG_16550 - select GENERIC_TBSYNC - select PPC_NATIVE - help - This option enables support for PA Semi's PWRficient line - of SoC processors, including PA6T-1682M - -config PPC_CELL - bool - default n - -config PPC_CELL_NATIVE - bool - select PPC_CELL - select PPC_DCR_MMIO - select PPC_OF_PLATFORM_PCI - select PPC_INDIRECT_IO - select PPC_NATIVE - select MPIC - default n - -config PPC_IBM_CELL_BLADE - bool "IBM Cell Blade" - depends on PPC_MULTIPLATFORM && PPC64 - select PPC_CELL_NATIVE - select PPC_RTAS - select MMIO_NVRAM - select PPC_UDBG_16550 - select UDBG_RTAS_CONSOLE - -config PPC_PS3 - bool "Sony PS3 (incomplete)" - depends on PPC_MULTIPLATFORM && PPC64 - select PPC_CELL - select USB_ARCH_HAS_OHCI - select USB_OHCI_LITTLE_ENDIAN - select USB_OHCI_BIG_ENDIAN_MMIO - select USB_ARCH_HAS_EHCI - select USB_EHCI_BIG_ENDIAN_MMIO - help - This option enables support for the Sony PS3 game console - and other platforms using the PS3 hypervisor. - Support for this platform is not yet complete, so - enabling this will not result in a bootable kernel on a - PS3 system. - -config PPC_CELLEB - bool "Toshiba's Cell Reference Set 'Celleb' Architecture" - depends on PPC_MULTIPLATFORM && PPC64 - select PPC_CELL - select PPC_OF_PLATFORM_PCI - select HAS_TXX9_SERIAL - select PPC_UDBG_BEAT - select USB_OHCI_BIG_ENDIAN_MMIO - select USB_EHCI_BIG_ENDIAN_MMIO - -config PPC_NATIVE - bool - depends on PPC_MULTIPLATFORM - help - Support for running natively on the hardware, i.e. without - a hypervisor. This option is not user-selectable but should - be selected by all platforms that need it. - -config UDBG_RTAS_CONSOLE - bool "RTAS based debug console" - depends on PPC_RTAS - default n - -config PPC_UDBG_BEAT - bool "BEAT based debug console" - depends on PPC_CELLEB - default n - -config XICS - depends on PPC_PSERIES - bool - default y - -config U3_DART - bool - depends on PPC_MULTIPLATFORM && PPC64 - default n - -config PPC_RTAS - bool - default n - -config RTAS_ERROR_LOGGING - bool - depends on PPC_RTAS - default n - -config RTAS_PROC - bool "Proc interface to RTAS" - depends on PPC_RTAS - default y - -config RTAS_FLASH - tristate "Firmware flash interface" - depends on PPC64 && RTAS_PROC - -config PPC_PMI - tristate "Support for PMI" - depends PPC_IBM_CELL_BLADE - help - PMI (Platform Management Interrupt) is a way to - communicate with the BMC (Baseboard Mangement Controller). - It is used in some IBM Cell blades. - default m - -config MMIO_NVRAM - bool - default n - -config MPIC_BROKEN_U3 - bool - depends on PPC_MAPLE - default y - -config IBMVIO - depends on PPC_PSERIES || PPC_ISERIES - bool - default y - -config IBMEBUS - depends on PPC_PSERIES - bool "Support for GX bus based adapters" - help - Bus device driver for GX bus based adapters. - -config PPC_MPC106 - bool - default n - -config PPC_970_NAP - bool - default n - -config PPC_INDIRECT_IO - bool - select GENERIC_IOMAP - default n - -config GENERIC_IOMAP - bool - default n - -source "drivers/cpufreq/Kconfig" - -config CPU_FREQ_PMAC - bool "Support for Apple PowerBooks" - depends on CPU_FREQ && ADB_PMU && PPC32 - select CPU_FREQ_TABLE - help - This adds support for frequency switching on Apple PowerBooks, - this currently includes some models of iBook & Titanium - PowerBook. - -config CPU_FREQ_PMAC64 - bool "Support for some Apple G5s" - depends on CPU_FREQ && PPC64 - select CPU_FREQ_TABLE - help - This adds support for frequency switching on Apple iMac G5, - and some of the more recent desktop G5 machines as well. - -config PPC601_SYNC_FIX - bool "Workarounds for PPC601 bugs" - depends on 6xx && (PPC_PREP || PPC_PMAC) - help - Some versions of the PPC601 (the first PowerPC chip) have bugs which - mean that extra synchronization instructions are required near - certain instructions, typically those that make major changes to the - CPU state. These extra instructions reduce performance slightly. - If you say N here, these extra instructions will not be included, - resulting in a kernel which will run faster but may not run at all - on some systems with the PPC601 chip. - - If in doubt, say Y here. - -config TAU - bool "On-chip CPU temperature sensor support" - depends on 6xx - help - G3 and G4 processors have an on-chip temperature sensor called the - 'Thermal Assist Unit (TAU)', which, in theory, can measure the on-die - temperature within 2-4 degrees Celsius. This option shows the current - on-die temperature in /proc/cpuinfo if the cpu supports it. - - Unfortunately, on some chip revisions, this sensor is very inaccurate - and in many cases, does not work at all, so don't assume the cpu - temp is actually what /proc/cpuinfo says it is. - -config TAU_INT - bool "Interrupt driven TAU driver (DANGEROUS)" - depends on TAU - ---help--- - The TAU supports an interrupt driven mode which causes an interrupt - whenever the temperature goes out of range. This is the fastest way - to get notified the temp has exceeded a range. With this option off, - a timer is used to re-check the temperature periodically. - - However, on some cpus it appears that the TAU interrupt hardware - is buggy and can cause a situation which would lead unexplained hard - lockups. - - Unless you are extending the TAU driver, or enjoy kernel/hardware - debugging, leave this option off. - -config TAU_AVERAGE - bool "Average high and low temp" - depends on TAU - ---help--- - The TAU hardware can compare the temperature to an upper and lower - bound. The default behavior is to show both the upper and lower - bound in /proc/cpuinfo. If the range is large, the temperature is - either changing a lot, or the TAU hardware is broken (likely on some - G4's). If the range is small (around 4 degrees), the temperature is - relatively stable. If you say Y here, a single temperature value, - halfway between the upper and lower bounds, will be reported in - /proc/cpuinfo. - - If in doubt, say N here. - -endmenu - -source arch/powerpc/platforms/embedded6xx/Kconfig -source arch/powerpc/platforms/4xx/Kconfig -source arch/powerpc/platforms/82xx/Kconfig -source arch/powerpc/platforms/83xx/Kconfig -source arch/powerpc/platforms/85xx/Kconfig -source arch/powerpc/platforms/86xx/Kconfig -source arch/powerpc/platforms/8xx/Kconfig -source arch/powerpc/platforms/cell/Kconfig -source arch/powerpc/platforms/ps3/Kconfig -source arch/powerpc/platforms/pasemi/Kconfig +source "arch/powerpc/platforms/Kconfig" menu "Kernel options" @@ -837,15 +457,6 @@ config CRASH_DUMP Don't change this unless you know what you are doing. -config EMBEDDEDBOOT - bool - depends on 8xx || 8260 - default y - -config PC_KEYBOARD - bool "PC PS/2 style Keyboard" - depends on 4xx || CPM2 - config PPCBUG_NVRAM bool "Enable reading PPCBUG NVRAM during boot" if PPLUS || LOPEC default y if PPC_PREP @@ -859,8 +470,6 @@ config IRQ_ALL_CPUS CPU. Generally saying Y is safe, although some problems have been reported with SMP Power Macintoshes with this option enabled. -source "arch/powerpc/platforms/pseries/Kconfig" - config NUMA bool "NUMA support" depends on PPC64 @@ -910,10 +519,10 @@ config PPC_64K_PAGES depends on PPC64 help This option changes the kernel logical page size to 64k. On machines - without processor support for 64k pages, the kernel will simulate - them by loading each individual 4k page on demand transparently, - while on hardware with such support, it will be used to map - normal application pages. + without processor support for 64k pages, the kernel will simulate + them by loading each individual 4k page on demand transparently, + while on hardware with such support, it will be used to map + normal application pages. config SCHED_SMT bool "SMT (Hyperthreading) scheduler support" @@ -931,8 +540,6 @@ config PROC_DEVICETREE an image of the device tree that the kernel copies from Open Firmware or other boot firmware. If unsure, say Y here. -source "arch/powerpc/platforms/prep/Kconfig" - config CMDLINE_BOOL bool "Default bootloader kernel arguments" @@ -967,6 +574,29 @@ config SECCOMP If unsure, say Y. Only embedded should say N here. +config WANT_DEVICE_TREE + bool + default n + +config DEVICE_TREE + string "Static device tree source file" + depends on WANT_DEVICE_TREE + help + This specifies the device tree source (.dts) file to be + compiled and included when building the bootwrapper. If a + relative filename is given, then it will be relative to + arch/powerpc/boot/dts. If you are not using the bootwrapper, + or do not need to build a dts into the bootwrapper, this + field is ignored. + + For example, this is required when building a cuImage target + for an older U-Boot, which cannot pass a device tree itself. + Such a kernel will not work with a newer U-Boot that tries to + pass a device tree (unless you tell it not to). If your U-Boot + does not mention a device tree in "help bootm", then use the + cuImage target and specify a device tree here. Otherwise, use + the uImage target and leave this field blank. + endmenu config ISA_DMA_API @@ -995,24 +625,17 @@ config GENERIC_ISA_DMA depends on PPC64 || POWER4 || 6xx && !CPM2 default y -config MPIC - bool - default n - -config MPIC_WEIRD - bool - default n - -config PPC_I8259 - bool - default n - config PPC_INDIRECT_PCI bool depends on PCI default y if 40x || 44x default n +config PPC_INDIRECT_PCI_BE + bool + depends PPC_INDIRECT_PCI + default n + config EISA bool @@ -1022,13 +645,18 @@ config SBUS config FSL_SOC bool +config FSL_PCIE + bool + depends on PPC_86xx + # Yes MCA RS/6000s exist but Linux-PPC does not currently support any config MCA bool config PCI bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \ - || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) || MPC7448HPC2 || PPC_PS3 + || PPC_MPC52xx || (EMBEDDED && (PPC_PSERIES || PPC_ISERIES)) \ + || MPC7448HPC2 || PPC_PS3 default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx \ && !PPC_85xx && !PPC_86xx default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS @@ -1228,12 +856,10 @@ source "fs/Kconfig" source "arch/powerpc/sysdev/qe_lib/Kconfig" -source "arch/powerpc/platforms/iseries/Kconfig" - source "lib/Kconfig" menu "Instrumentation Support" - depends on EXPERIMENTAL + depends on EXPERIMENTAL source "arch/powerpc/oprofile/Kconfig" diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index d39d133..86aa374 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug @@ -18,6 +18,15 @@ config DEBUG_STACK_USAGE This option will slow down process creation somewhat. +config DEBUG_PAGEALLOC + bool "Debug page memory allocations" + depends on DEBUG_KERNEL && !SOFTWARE_SUSPEND + help + Unmap pages from the kernel linear mapping after free_pages(). + This results in a large slowdown, but helps to find certain types + of memory corruptions. + + config HCALL_STATS bool "Hypervisor call instrumentation" depends on PPC_PSERIES && DEBUG_FS @@ -132,8 +141,7 @@ config BOOTX_TEXT config SERIAL_TEXT_DEBUG bool "Support for early boot texts over serial port" - depends on 4xx || LOPEC || MV64X60 || PPLUS || PRPMC800 || \ - PPC_GEN550 || PPC_MPC52xx + depends on 4xx config PPC_EARLY_DEBUG bool "Early debugging (dangerous)" diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index a00fe72..7949920 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -102,9 +102,9 @@ CFLAGS += $(call cc-option,-mno-altivec) # kernel considerably. CFLAGS += $(call cc-option,-funit-at-a-time) -ifndef CONFIG_FSL_BOOKE -CFLAGS += -mstring -endif +# Never use string load/store instructions as they are +# often slow when they are implemented at all +CFLAGS += -mno-string ifeq ($(CONFIG_6xx),y) CFLAGS += -mcpu=powerpc @@ -148,7 +148,7 @@ all: $(KBUILD_IMAGE) CPPFLAGS_vmlinux.lds := -Upowerpc -BOOT_TARGETS = zImage zImage.initrd uImage +BOOT_TARGETS = zImage zImage.initrd uImage cuImage PHONY += $(BOOT_TARGETS) @@ -166,6 +166,9 @@ define archhelp @echo ' *_defconfig - Select default config from arch/$(ARCH)/configs' endef +install: + $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install + archclean: $(Q)$(MAKE) $(clean)=$(boot) diff --git a/arch/powerpc/boot/.gitignore b/arch/powerpc/boot/.gitignore index 0734b2f..eec7af7 100644 --- a/arch/powerpc/boot/.gitignore +++ b/arch/powerpc/boot/.gitignore @@ -18,6 +18,9 @@ kernel-vmlinux.strip.c kernel-vmlinux.strip.gz mktree uImage +cuImage +cuImage.bin.gz +cuImage.elf zImage zImage.chrp zImage.coff diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index dc77940..3716594 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -40,10 +40,11 @@ zliblinuxheader := zlib.h zconf.h zutil.h $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) \ $(addprefix $(obj)/,$(zlibheader)) -src-wlib := string.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ - ns16550.c serial.c simple_alloc.c div64.S util.S $(zlib) -src-plat := of.c -src-boot := crt0.S $(src-wlib) $(src-plat) empty.c +src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ + ns16550.c serial.c simple_alloc.c div64.S util.S \ + gunzip_util.c elf_util.c $(zlib) devtree.c +src-plat := of.c cuboot-83xx.c cuboot-85xx.c +src-boot := $(src-wlib) $(src-plat) empty.c src-boot := $(addprefix $(obj)/, $(src-boot)) obj-boot := $(addsuffix .o, $(basename $(src-boot))) @@ -75,7 +76,7 @@ $(obj)/zImage.lds $(obj)/zImage.coff.lds: $(obj)/%: $(srctree)/$(src)/%.S @cp $< $@ clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \ - empty.c zImage zImage.coff.lds zImage.lds zImage.sandpoint + empty.c zImage.coff.lds zImage.lds quiet_cmd_bootcc = BOOTCC $@ cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $< @@ -84,23 +85,25 @@ quiet_cmd_bootas = BOOTAS $@ cmd_bootas = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $< quiet_cmd_bootar = BOOTAR $@ - cmd_bootar = $(CROSS32AR) -cr $@.$$$$ $^; mv $@.$$$$ $@ + cmd_bootar = $(CROSS32AR) -cr $@.$$$$ $(filter-out FORCE,$^); mv $@.$$$$ $@ -$(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c +$(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c FORCE $(call if_changed_dep,bootcc) -$(patsubst %.S,%.o, $(filter %.S, $(src-boot))): %.o: %.S +$(patsubst %.S,%.o, $(filter %.S, $(src-boot))): %.o: %.S FORCE $(call if_changed_dep,bootas) -$(obj)/wrapper.a: $(obj-wlib) - $(call cmd,bootar) +$(obj)/wrapper.a: $(obj-wlib) FORCE + $(call if_changed,bootar) hostprogs-y := addnote addRamDisk hack-coff mktree -extra-y := $(obj)/crt0.o $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \ +targets += $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a) +extra-y := $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \ $(obj)/zImage.lds $(obj)/zImage.coff.lds wrapper :=$(srctree)/$(src)/wrapper -wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) +wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) \ + $(wrapper) FORCE ############# # Bits for building various flavours of zImage @@ -113,50 +116,10 @@ CROSSWRAP := -C "$(CROSS_COMPILE)" endif endif +# args (to if_changed): 1 = (this rule), 2 = platform, 3 = dts 4=dtb 5=initrd quiet_cmd_wrap = WRAP $@ - cmd_wrap =$(CONFIG_SHELL) $(wrapper) -c -o $@ -p $2 $(CROSSWRAP) vmlinux -quiet_cmd_wrap_initrd = WRAP $@ - cmd_wrap_initrd =$(CONFIG_SHELL) $(wrapper) -c -o $@ -p $2 $(CROSSWRAP) \ - -i $(obj)/ramdisk.image.gz vmlinux - -$(obj)/zImage.chrp: vmlinux $(wrapperbits) - $(call cmd,wrap,chrp) - -$(obj)/zImage.initrd.chrp: vmlinux $(wrapperbits) - $(call cmd,wrap_initrd,chrp) - -$(obj)/zImage.pseries: vmlinux $(wrapperbits) - $(call cmd,wrap,pseries) - -$(obj)/zImage.initrd.pseries: vmlinux $(wrapperbits) - $(call cmd,wrap_initrd,pseries) - -$(obj)/zImage.pmac: vmlinux $(wrapperbits) - $(call cmd,wrap,pmac) - -$(obj)/zImage.initrd.pmac: vmlinux $(wrapperbits) - $(call cmd,wrap_initrd,pmac) - -$(obj)/zImage.coff: vmlinux $(wrapperbits) - $(call cmd,wrap,pmaccoff) - -$(obj)/zImage.initrd.coff: vmlinux $(wrapperbits) - $(call cmd,wrap_initrd,pmaccoff) - -$(obj)/zImage.miboot: vmlinux $(wrapperbits) - $(call cmd,wrap,miboot) - -$(obj)/zImage.initrd.miboot: vmlinux $(wrapperbits) - $(call cmd,wrap_initrd,miboot) - -$(obj)/zImage.ps3: vmlinux - $(STRIP) -s -R .comment $< -o $@ - -$(obj)/zImage.initrd.ps3: vmlinux - @echo " WARNING zImage.initrd.ps3 not supported (yet)" - -$(obj)/uImage: vmlinux $(wrapperbits) - $(call cmd,wrap,uboot) + cmd_wrap =$(CONFIG_SHELL) $(wrapper) -c -o $@ -p $2 $(CROSSWRAP) \ + $(if $3, -s $3)$(if $4, -d $4)$(if $5, -i $5) vmlinux image-$(CONFIG_PPC_PSERIES) += zImage.pseries image-$(CONFIG_PPC_MAPLE) += zImage.pseries @@ -166,7 +129,7 @@ image-$(CONFIG_PPC_CELLEB) += zImage.pseries image-$(CONFIG_PPC_CHRP) += zImage.chrp image-$(CONFIG_PPC_EFIKA) += zImage.chrp image-$(CONFIG_PPC_PMAC) += zImage.pmac -image-$(CONFIG_DEFAULT_UIMAGE) += uImage +image-$(CONFIG_DEFAULT_UIMAGE) += uImage cuImage # For 32-bit powermacs, build the COFF and miboot images # as well as the ELF images. @@ -174,16 +137,55 @@ ifeq ($(CONFIG_PPC32),y) image-$(CONFIG_PPC_PMAC) += zImage.coff zImage.miboot endif +initrd- := $(patsubst zImage%, zImage.initrd%, $(image-n) $(image-)) initrd-y := $(patsubst zImage%, zImage.initrd%, $(image-y)) +initrd-y := $(filter-out $(image-y), $(initrd-y)) +targets += $(image-y) $(initrd-y) + +$(addprefix $(obj)/, $(initrd-y)): $(obj)/ramdisk.image.gz + +# Don't put the ramdisk on the pattern rule; when its missing make will try +# the pattern rule with less dependencies that also matches (even with the +# hard dependency listed). +$(obj)/zImage.initrd.%: vmlinux $(wrapperbits) + $(call if_changed,wrap,$*,,,$(obj)/ramdisk.image.gz) + +$(obj)/zImage.%: vmlinux $(wrapperbits) + $(call if_changed,wrap,$*) + +$(obj)/zImage.ps3: vmlinux + $(STRIP) -s -R .comment $< -o $@ + +$(obj)/zImage.initrd.ps3: vmlinux + @echo " WARNING zImage.initrd.ps3 not supported (yet)" + +$(obj)/uImage: vmlinux $(wrapperbits) + $(call if_changed,wrap,uboot) + +cuboot-plat-$(CONFIG_83xx) += 83xx +cuboot-plat-$(CONFIG_85xx) += 85xx +cuboot-plat-y += unknown-platform + +dts = $(if $(shell echo $(CONFIG_DEVICE_TREE) | grep '^/'),\ + ,$(srctree)/$(src)/dts/)$(CONFIG_DEVICE_TREE) + +$(obj)/cuImage: vmlinux $(wrapperbits) + $(call if_changed,wrap,cuboot-$(word 1,$(cuboot-plat-y)),$(dts)) $(obj)/zImage: $(addprefix $(obj)/, $(image-y)) @rm -f $@; ln $< $@ $(obj)/zImage.initrd: $(addprefix $(obj)/, $(initrd-y)) @rm -f $@; ln $< $@ -install: $(CONFIGURE) $(image-y) +install: $(CONFIGURE) $(addprefix $(obj)/, $(image-y)) sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $< -clean-files += $(addprefix $(objtree)/, $(obj-boot) vmlinux.strip.gz) -clean-files += $(addprefix $(objtree)/, $(obj-boot) vmlinux.bin.gz) -clean-files += $(image-) +# anything not in $(targets) +clean-files += $(image-) $(initrd-) zImage zImage.initrd \ + cuImage.elf cuImage.bin.gz + +# clean up files cached by wrapper +clean-kernel := vmlinux.strip vmlinux.bin +clean-kernel += $(addsuffix .gz,$(clean-kernel)) +# If not absolute clean-files are relative to $(obj). +clean-files += $(addprefix $(objtree)/, $(clean-kernel)) diff --git a/arch/powerpc/boot/crt0.S b/arch/powerpc/boot/crt0.S index 70e65b1..5a4215c 100644 --- a/arch/powerpc/boot/crt0.S +++ b/arch/powerpc/boot/crt0.S @@ -16,8 +16,11 @@ _zimage_start_opd: .long _zimage_start, 0, 0, 0 + .weak _zimage_start .globl _zimage_start _zimage_start: + .globl _zimage_start_lib +_zimage_start_lib: /* Work out the offset between the address we were linked at and the address where we're running. */ bl 1f @@ -44,7 +47,7 @@ _zimage_start: addi r9,r9,4 bdnz 2b - /* Do a cache flush for our text, in case OF didn't */ + /* Do a cache flush for our text, in case the loader didn't */ 3: lis r9,_start@ha addi r9,r9,_start@l add r9,r0,r9 @@ -59,6 +62,34 @@ _zimage_start: sync isync - mr r6,r1 - b start + /* Clear the BSS */ + lis r9,__bss_start@ha + addi r9,r9,__bss_start@l + add r9,r0,r9 + lis r8,_end@ha + addi r8,r8,_end@l + add r8,r0,r8 + li r10,0 +5: stw r10,0(r9) + addi r9,r9,4 + cmplw cr0,r9,r8 + blt 5b + /* Possibly set up a custom stack */ +.weak _platform_stack_top + lis r8,_platform_stack_top@ha + addi r8,r8,_platform_stack_top@l + cmpwi r8,0 + beq 6f + add r8,r0,r8 + lwz r1,0(r8) + add r1,r0,r1 + li r0,0 + stwu r0,-16(r1) /* establish a stack frame */ +6: + + /* Call platform_init() */ + bl platform_init + + /* Call start */ + b start diff --git a/arch/powerpc/boot/cuboot-83xx.c b/arch/powerpc/boot/cuboot-83xx.c new file mode 100644 index 0000000..6cbc20a --- /dev/null +++ b/arch/powerpc/boot/cuboot-83xx.c @@ -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; +} diff --git a/arch/powerpc/boot/cuboot-85xx.c b/arch/powerpc/boot/cuboot-85xx.c new file mode 100644 index 0000000..f88ba00 --- /dev/null +++ b/arch/powerpc/boot/cuboot-85xx.c @@ -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; +} diff --git a/arch/powerpc/boot/devtree.c b/arch/powerpc/boot/devtree.c new file mode 100644 index 0000000..c995155 --- /dev/null +++ b/arch/powerpc/boot/devtree.c @@ -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); +} diff --git a/arch/powerpc/boot/dts/kuroboxHD.dts b/arch/powerpc/boot/dts/kuroboxHD.dts index b897918..157dc98 100644 --- a/arch/powerpc/boot/dts/kuroboxHD.dts +++ b/arch/powerpc/boot/dts/kuroboxHD.dts @@ -29,7 +29,6 @@ build with: "dtc -f -I dts -O dtb -o kuroboxHD.dtb -V 16 kuroboxHD.dts" cpus { linux,phandle = <2000>; - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; @@ -126,17 +125,17 @@ build with: "dtc -f -I dts -O dtb -o kuroboxHD.dtb -V 16 kuroboxHD.dts" interrupt-parent = <4400>; interrupt-map-mask = <f800 0 0 7>; interrupt-map = < - /* IDSEL 0x11 - IRQ0 ETH */ + /* IDSEL 11 - IRQ0 ETH */ 5800 0 0 1 4400 0 1 5800 0 0 2 4400 1 1 5800 0 0 3 4400 2 1 5800 0 0 4 4400 3 1 - /* IDSEL 0x12 - IRQ1 IDE0 */ + /* IDSEL 12 - IRQ1 IDE0 */ 6000 0 0 1 4400 1 1 6000 0 0 2 4400 2 1 6000 0 0 3 4400 3 1 6000 0 0 4 4400 0 1 - /* IDSEL 0x14 - IRQ3 USB2.0 */ + /* IDSEL 14 - IRQ3 USB2.0 */ 7000 0 0 1 4400 3 1 7000 0 0 2 4400 3 1 7000 0 0 3 4400 3 1 diff --git a/arch/powerpc/boot/dts/kuroboxHG.dts b/arch/powerpc/boot/dts/kuroboxHG.dts index 7531027..919eb29 100644 --- a/arch/powerpc/boot/dts/kuroboxHG.dts +++ b/arch/powerpc/boot/dts/kuroboxHG.dts @@ -29,7 +29,6 @@ build with: "dtc -f -I dts -O dtb -o kuroboxHG.dtb -V 16 kuroboxHG.dts" cpus { linux,phandle = <2000>; - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; @@ -126,17 +125,17 @@ build with: "dtc -f -I dts -O dtb -o kuroboxHG.dtb -V 16 kuroboxHG.dts" interrupt-parent = <4400>; interrupt-map-mask = <f800 0 0 7>; interrupt-map = < - /* IDSEL 0x11 - IRQ0 ETH */ + /* IDSEL 11 - IRQ0 ETH */ 5800 0 0 1 4400 0 1 5800 0 0 2 4400 1 1 5800 0 0 3 4400 2 1 5800 0 0 4 4400 3 1 - /* IDSEL 0x12 - IRQ1 IDE0 */ + /* IDSEL 12 - IRQ1 IDE0 */ 6000 0 0 1 4400 1 1 6000 0 0 2 4400 2 1 6000 0 0 3 4400 3 1 6000 0 0 4 4400 0 1 - /* IDSEL 0x14 - IRQ3 USB2.0 */ + /* IDSEL 14 - IRQ3 USB2.0 */ 7000 0 0 1 4400 3 1 7000 0 0 2 4400 3 1 7000 0 0 3 4400 3 1 diff --git a/arch/powerpc/boot/dts/lite5200.dts b/arch/powerpc/boot/dts/lite5200.dts index c03103c..ba54c6b 100644 --- a/arch/powerpc/boot/dts/lite5200.dts +++ b/arch/powerpc/boot/dts/lite5200.dts @@ -24,7 +24,6 @@ #size-cells = <1>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/lite5200b.dts b/arch/powerpc/boot/dts/lite5200b.dts index 3875ca9..2e00308 100644 --- a/arch/powerpc/boot/dts/lite5200b.dts +++ b/arch/powerpc/boot/dts/lite5200b.dts @@ -24,7 +24,6 @@ #size-cells = <1>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/mpc7448hpc2.dts b/arch/powerpc/boot/dts/mpc7448hpc2.dts index 41d0720c..6fa3754 100644 --- a/arch/powerpc/boot/dts/mpc7448hpc2.dts +++ b/arch/powerpc/boot/dts/mpc7448hpc2.dts @@ -19,7 +19,6 @@ linux,phandle = <100>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells =<0>; linux,phandle = <200>; diff --git a/arch/powerpc/boot/dts/mpc8272ads.dts b/arch/powerpc/boot/dts/mpc8272ads.dts index 260b2e4..423eedc 100644 --- a/arch/powerpc/boot/dts/mpc8272ads.dts +++ b/arch/powerpc/boot/dts/mpc8272ads.dts @@ -17,7 +17,6 @@ linux,phandle = <100>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; linux,phandle = <200>; diff --git a/arch/powerpc/boot/dts/mpc8313erdb.dts b/arch/powerpc/boot/dts/mpc8313erdb.dts index 6d72190..a1533cc 100644 --- a/arch/powerpc/boot/dts/mpc8313erdb.dts +++ b/arch/powerpc/boot/dts/mpc8313erdb.dts @@ -16,7 +16,6 @@ #size-cells = <1>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/mpc832x_mds.dts b/arch/powerpc/boot/dts/mpc832x_mds.dts index 06b3106..c798491 100644 --- a/arch/powerpc/boot/dts/mpc832x_mds.dts +++ b/arch/powerpc/boot/dts/mpc832x_mds.dts @@ -16,7 +16,6 @@ #size-cells = <1>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/mpc832x_rdb.dts b/arch/powerpc/boot/dts/mpc832x_rdb.dts new file mode 100644 index 0000000..b55bced --- /dev/null +++ b/arch/powerpc/boot/dts/mpc832x_rdb.dts @@ -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>; + }; + }; +}; diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts index 61b550b..db0d003 100644 --- a/arch/powerpc/boot/dts/mpc8349emitx.dts +++ b/arch/powerpc/boot/dts/mpc8349emitx.dts @@ -15,7 +15,6 @@ #size-cells = <1>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/mpc8349emitxgp.dts b/arch/powerpc/boot/dts/mpc8349emitxgp.dts index b2e1a5e..f636528 100644 --- a/arch/powerpc/boot/dts/mpc8349emitxgp.dts +++ b/arch/powerpc/boot/dts/mpc8349emitxgp.dts @@ -15,7 +15,6 @@ #size-cells = <1>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/mpc834x_mds.dts b/arch/powerpc/boot/dts/mpc834x_mds.dts index e4b43c2..07bcc51 100644 --- a/arch/powerpc/boot/dts/mpc834x_mds.dts +++ b/arch/powerpc/boot/dts/mpc834x_mds.dts @@ -16,7 +16,6 @@ #size-cells = <1>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts index 4fe45c0..7f578eb 100644 --- a/arch/powerpc/boot/dts/mpc836x_mds.dts +++ b/arch/powerpc/boot/dts/mpc836x_mds.dts @@ -21,7 +21,6 @@ #size-cells = <1>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/mpc8540ads.dts b/arch/powerpc/boot/dts/mpc8540ads.dts index 3c0917f..f261d64 100644 --- a/arch/powerpc/boot/dts/mpc8540ads.dts +++ b/arch/powerpc/boot/dts/mpc8540ads.dts @@ -17,7 +17,6 @@ #size-cells = <1>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/mpc8541cds.dts b/arch/powerpc/boot/dts/mpc8541cds.dts index 2a1ae76..5fdcb69 100644 --- a/arch/powerpc/boot/dts/mpc8541cds.dts +++ b/arch/powerpc/boot/dts/mpc8541cds.dts @@ -17,7 +17,6 @@ #size-cells = <1>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/mpc8544ds.dts b/arch/powerpc/boot/dts/mpc8544ds.dts new file mode 100644 index 0000000..6b08460 --- /dev/null +++ b/arch/powerpc/boot/dts/mpc8544ds.dts @@ -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; + }; + }; +}; diff --git a/arch/powerpc/boot/dts/mpc8548cds.dts b/arch/powerpc/boot/dts/mpc8548cds.dts index 7eb5d81..b2b2200 100644 --- a/arch/powerpc/boot/dts/mpc8548cds.dts +++ b/arch/powerpc/boot/dts/mpc8548cds.dts @@ -17,7 +17,6 @@ #size-cells = <1>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/mpc8555cds.dts b/arch/powerpc/boot/dts/mpc8555cds.dts index 5f9c102..68a4795 100644 --- a/arch/powerpc/boot/dts/mpc8555cds.dts +++ b/arch/powerpc/boot/dts/mpc8555cds.dts @@ -17,7 +17,6 @@ #size-cells = <1>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/mpc8560ads.dts b/arch/powerpc/boot/dts/mpc8560ads.dts index 1050263..1f2afe9 100644 --- a/arch/powerpc/boot/dts/mpc8560ads.dts +++ b/arch/powerpc/boot/dts/mpc8560ads.dts @@ -17,7 +17,6 @@ #size-cells = <1>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/mpc8568mds.dts b/arch/powerpc/boot/dts/mpc8568mds.dts index bf49d8c..7361b36 100644 --- a/arch/powerpc/boot/dts/mpc8568mds.dts +++ b/arch/powerpc/boot/dts/mpc8568mds.dts @@ -21,7 +21,6 @@ #size-cells = <1>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/mpc8641_hpcn.dts b/arch/powerpc/boot/dts/mpc8641_hpcn.dts index 8a4995a..260b264 100644 --- a/arch/powerpc/boot/dts/mpc8641_hpcn.dts +++ b/arch/powerpc/boot/dts/mpc8641_hpcn.dts @@ -17,7 +17,6 @@ #size-cells = <1>; cpus { - #cpus = <2>; #address-cells = <1>; #size-cells = <0>; @@ -300,6 +299,30 @@ }; }; + + pci@9000 { + compatible = "86xx"; + device_type = "pci"; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + reg = <9000 1000>; + bus-range = <0 ff>; + ranges = <02000000 0 a0000000 a0000000 0 20000000 + 01000000 0 00000000 e3000000 0 00100000>; + clock-frequency = <1fca055>; + interrupt-parent = <&mpic>; + interrupts = <19 2>; + interrupt-map-mask = <f800 0 0 7>; + interrupt-map = < + /* IDSEL 0x0 */ + 0000 0 0 1 &mpic 44 1 + 0000 0 0 2 &mpic 45 1 + 0000 0 0 3 &mpic 46 1 + 0000 0 0 4 &mpic 47 1 + >; + }; + mpic: pic@40000 { clock-frequency = <0>; interrupt-controller; diff --git a/arch/powerpc/boot/dts/mpc866ads.dts b/arch/powerpc/boot/dts/mpc866ads.dts index 2b56b5d..c0d06fd 100644 --- a/arch/powerpc/boot/dts/mpc866ads.dts +++ b/arch/powerpc/boot/dts/mpc866ads.dts @@ -18,7 +18,6 @@ linux,phandle = <100>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; linux,phandle = <200>; diff --git a/arch/powerpc/boot/dts/mpc885ads.dts b/arch/powerpc/boot/dts/mpc885ads.dts index faecd08..110bf61 100644 --- a/arch/powerpc/boot/dts/mpc885ads.dts +++ b/arch/powerpc/boot/dts/mpc885ads.dts @@ -18,7 +18,6 @@ linux,phandle = <100>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; linux,phandle = <200>; diff --git a/arch/powerpc/boot/elf.h b/arch/powerpc/boot/elf.h index d4828fc..1941bc5 100644 --- a/arch/powerpc/boot/elf.h +++ b/arch/powerpc/boot/elf.h @@ -146,4 +146,12 @@ typedef struct elf64_phdr { #define ELFOSABI_NONE 0 #define ELFOSABI_LINUX 3 +struct elf_info { + unsigned long loadsize; + unsigned long memsize; + unsigned long elfoffset; +}; +int parse_elf64(void *hdr, struct elf_info *info); +int parse_elf32(void *hdr, struct elf_info *info); + #endif /* _PPC_BOOT_ELF_H_ */ diff --git a/arch/powerpc/boot/elf_util.c b/arch/powerpc/boot/elf_util.c new file mode 100644 index 0000000..7454aa4 --- /dev/null +++ b/arch/powerpc/boot/elf_util.c @@ -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; +} diff --git a/arch/powerpc/boot/flatdevtree.c b/arch/powerpc/boot/flatdevtree.c index c76c194..d00fbd9 100644 --- a/arch/powerpc/boot/flatdevtree.c +++ b/arch/powerpc/boot/flatdevtree.c @@ -29,12 +29,20 @@ #define _ALIGN(x, al) (((x) + (al) - 1) & ~((al) - 1)) +static char *ft_root_node(struct ft_cxt *cxt) +{ + return cxt->rgn[FT_STRUCT].start; +} + /* Routines for keeping node ptrs returned by ft_find_device current */ /* First entry not used b/c it would return 0 and be taken as NULL/error */ -static void *ft_node_add(struct ft_cxt *cxt, char *node) +static void *ft_get_phandle(struct ft_cxt *cxt, char *node) { unsigned int i; + if (!node) + return NULL; + for (i = 1; i < cxt->nodes_used; i++) /* already there? */ if (cxt->node_tbl[i] == node) return (void *)i; @@ -238,7 +246,7 @@ static int ft_shuffle(struct ft_cxt *cxt, char **pp, enum ft_rgn_id rgn, if (rgn == FT_STRUCT) ft_node_update_before(cxt, p, -nextra); } - *p -= nextra; + *pp -= nextra; cxt->rgn[rgn].start -= nextra; cxt->rgn[rgn].size += nextra; return 1; @@ -253,8 +261,14 @@ static int ft_make_space(struct ft_cxt *cxt, char **pp, enum ft_rgn_id rgn, char *str, *next; enum ft_rgn_id r; - if (!cxt->isordered && !ft_reorder(cxt, nextra)) - return 0; + if (!cxt->isordered) { + unsigned long rgn_off = *pp - cxt->rgn[rgn].start; + + if (!ft_reorder(cxt, nextra)) + return 0; + + *pp = cxt->rgn[rgn].start + rgn_off; + } if (ft_shuffle(cxt, pp, rgn, nextra)) return 1; @@ -415,7 +429,7 @@ int ft_prop(struct ft_cxt *cxt, const char *name, const void *data, { int off, len; - off = lookup_string(cxt, name); + off = map_string(cxt, name); if (off == NO_STRING) return -1; @@ -590,7 +604,7 @@ int ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size) void ft_begin_tree(struct ft_cxt *cxt) { - cxt->p = cxt->rgn[FT_STRUCT].start; + cxt->p = ft_root_node(cxt); } void ft_end_tree(struct ft_cxt *cxt) @@ -636,8 +650,21 @@ void *ft_find_device(struct ft_cxt *cxt, const char *srch_path) /* require absolute path */ if (srch_path[0] != '/') return NULL; - node = ft_find_descendent(cxt, cxt->rgn[FT_STRUCT].start, srch_path); - return ft_node_add(cxt, node); + node = ft_find_descendent(cxt, ft_root_node(cxt), srch_path); + return ft_get_phandle(cxt, node); +} + +void *ft_find_device_rel(struct ft_cxt *cxt, const void *top, + const char *srch_path) +{ + char *node; + + node = ft_node_ph2node(cxt, top); + if (node == NULL) + return NULL; + + node = ft_find_descendent(cxt, node, srch_path); + return ft_get_phandle(cxt, node); } void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path) @@ -701,23 +728,18 @@ void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path) return NULL; } -void *ft_get_parent(struct ft_cxt *cxt, const void *phandle) +void *__ft_get_parent(struct ft_cxt *cxt, void *node) { - void *node; int d; struct ft_atom atom; char *p; - node = ft_node_ph2node(cxt, phandle); - if (node == NULL) - return NULL; - for (d = 0; cxt->genealogy[d] != NULL; ++d) if (cxt->genealogy[d] == node) - return cxt->genealogy[d > 0 ? d - 1 : 0]; + return d > 0 ? cxt->genealogy[d - 1] : NULL; /* have to do it the hard way... */ - p = cxt->rgn[FT_STRUCT].start; + p = ft_root_node(cxt); d = 0; while ((p = ft_next(cxt, p, &atom)) != NULL) { switch (atom.tag) { @@ -726,7 +748,7 @@ void *ft_get_parent(struct ft_cxt *cxt, const void *phandle) if (node == atom.data) { /* found it */ cxt->genealogy[d + 1] = NULL; - return d > 0 ? cxt->genealogy[d - 1] : node; + return d > 0 ? cxt->genealogy[d - 1] : NULL; } ++d; break; @@ -738,41 +760,131 @@ void *ft_get_parent(struct ft_cxt *cxt, const void *phandle) return NULL; } -int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname, - void *buf, const unsigned int buflen) +void *ft_get_parent(struct ft_cxt *cxt, const void *phandle) { - struct ft_atom atom; - void *node; - char *p; - int depth; - unsigned int size; - - node = ft_node_ph2node(cxt, phandle); + void *node = ft_node_ph2node(cxt, phandle); if (node == NULL) - return -1; + return NULL; - depth = 0; - p = (char *)node; + node = __ft_get_parent(cxt, node); + return ft_get_phandle(cxt, node); +} - while ((p = ft_next(cxt, p, &atom)) != NULL) { +static const void *__ft_get_prop(struct ft_cxt *cxt, void *node, + const char *propname, unsigned int *len) +{ + struct ft_atom atom; + int depth = 0; + + while ((node = ft_next(cxt, node, &atom)) != NULL) { switch (atom.tag) { case OF_DT_BEGIN_NODE: ++depth; break; + case OF_DT_PROP: - if ((depth != 1) || strcmp(atom.name, propname)) + if (depth != 1 || strcmp(atom.name, propname)) break; - size = min(atom.size, buflen); - memcpy(buf, atom.data, size); - return atom.size; + + if (len) + *len = atom.size; + + return atom.data; + case OF_DT_END_NODE: if (--depth <= 0) - return -1; + return NULL; } } + + return NULL; +} + +int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname, + void *buf, const unsigned int buflen) +{ + const void *data; + unsigned int size; + + void *node = ft_node_ph2node(cxt, phandle); + if (!node) + return -1; + + data = __ft_get_prop(cxt, node, propname, &size); + if (data) { + unsigned int clipped_size = min(size, buflen); + memcpy(buf, data, clipped_size); + return size; + } + return -1; } +void *__ft_find_node_by_prop_value(struct ft_cxt *cxt, void *prev, + const char *propname, const char *propval, + unsigned int proplen) +{ + struct ft_atom atom; + char *p = ft_root_node(cxt); + char *next; + int past_prev = prev ? 0 : 1; + int depth = -1; + + while ((next = ft_next(cxt, p, &atom)) != NULL) { + const void *data; + unsigned int size; + + switch (atom.tag) { + case OF_DT_BEGIN_NODE: + depth++; + + if (prev == p) { + past_prev = 1; + break; + } + + if (!past_prev || depth < 1) + break; + + data = __ft_get_prop(cxt, p, propname, &size); + if (!data || size != proplen) + break; + if (memcmp(data, propval, size)) + break; + + return p; + + case OF_DT_END_NODE: + if (depth-- == 0) + return NULL; + + break; + } + + p = next; + } + + return NULL; +} + +void *ft_find_node_by_prop_value(struct ft_cxt *cxt, const void *prev, + const char *propname, const char *propval, + int proplen) +{ + void *node = NULL; + + if (prev) { + node = ft_node_ph2node(cxt, prev); + + if (!node) + return NULL; + } + + node = __ft_find_node_by_prop_value(cxt, node, propname, + propval, proplen); + return ft_get_phandle(cxt, node); +} + int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname, const void *buf, const unsigned int buflen) { @@ -849,19 +961,26 @@ int ft_del_prop(struct ft_cxt *cxt, const void *phandle, const char *propname) return -1; } -void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *path) +void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *name) { struct ft_atom atom; char *p, *next; int depth = 0; - p = cxt->rgn[FT_STRUCT].start; + if (parent) { + p = ft_node_ph2node(cxt, parent); + if (!p) + return NULL; + } else { + p = ft_root_node(cxt); + } + while ((next = ft_next(cxt, p, &atom)) != NULL) { switch (atom.tag) { case OF_DT_BEGIN_NODE: ++depth; - if (depth == 1 && strcmp(atom.name, path) == 0) - /* duplicate node path, return error */ + if (depth == 1 && strcmp(atom.name, name) == 0) + /* duplicate node name, return error */ return NULL; break; case OF_DT_END_NODE: @@ -870,7 +989,7 @@ void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *path) break; /* end of node, insert here */ cxt->p = p; - ft_begin_node(cxt, path); + ft_begin_node(cxt, name); ft_end_node(cxt); return p; } diff --git a/arch/powerpc/boot/flatdevtree.h b/arch/powerpc/boot/flatdevtree.h index b9cd9f6..cb26325 100644 --- a/arch/powerpc/boot/flatdevtree.h +++ b/arch/powerpc/boot/flatdevtree.h @@ -97,10 +97,17 @@ int ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size); void ft_dump_blob(const void *bphp); void ft_merge_blob(struct ft_cxt *cxt, void *blob); void *ft_find_device(struct ft_cxt *cxt, const char *srch_path); +void *ft_find_device_rel(struct ft_cxt *cxt, const void *top, + const char *srch_path); void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path); int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname, void *buf, const unsigned int buflen); int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname, const void *buf, const unsigned int buflen); +void *ft_get_parent(struct ft_cxt *cxt, const void *phandle); +void *ft_find_node_by_prop_value(struct ft_cxt *cxt, const void *prev, + const char *propname, const char *propval, + int proplen); +void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *name); #endif /* FLATDEVTREE_H */ diff --git a/arch/powerpc/boot/flatdevtree_misc.c b/arch/powerpc/boot/flatdevtree_misc.c index 04da38f..4341e65 100644 --- a/arch/powerpc/boot/flatdevtree_misc.c +++ b/arch/powerpc/boot/flatdevtree_misc.c @@ -16,24 +16,43 @@ static struct ft_cxt cxt; -static void *ft_finddevice(const char *name) +static void *fdtm_finddevice(const char *name) { return ft_find_device(&cxt, name); } -static int ft_getprop(const void *phandle, const char *propname, void *buf, - const int buflen) +static int fdtm_getprop(const void *phandle, const char *propname, + void *buf, const int buflen) { return ft_get_prop(&cxt, phandle, propname, buf, buflen); } -static int ft_setprop(const void *phandle, const char *propname, - const void *buf, const int buflen) +static int fdtm_setprop(const void *phandle, const char *propname, + const void *buf, const int buflen) { return ft_set_prop(&cxt, phandle, propname, buf, buflen); } -static unsigned long ft_finalize(void) +static void *fdtm_get_parent(const void *phandle) +{ + return ft_get_parent(&cxt, phandle); +} + +static void *fdtm_create_node(const void *phandle, const char *name) +{ + return ft_create_node(&cxt, phandle, name); +} + +static void *fdtm_find_node_by_prop_value(const void *prev, + const char *propname, + const char *propval, + int proplen) +{ + return ft_find_node_by_prop_value(&cxt, prev, propname, + propval, proplen); +} + +static unsigned long fdtm_finalize(void) { ft_end_tree(&cxt); return (unsigned long)cxt.bph; @@ -41,10 +60,13 @@ static unsigned long ft_finalize(void) int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device) { - dt_ops.finddevice = ft_finddevice; - dt_ops.getprop = ft_getprop; - dt_ops.setprop = ft_setprop; - dt_ops.finalize = ft_finalize; + dt_ops.finddevice = fdtm_finddevice; + dt_ops.getprop = fdtm_getprop; + dt_ops.setprop = fdtm_setprop; + dt_ops.get_parent = fdtm_get_parent; + dt_ops.create_node = fdtm_create_node; + dt_ops.find_node_by_prop_value = fdtm_find_node_by_prop_value; + dt_ops.finalize = fdtm_finalize; return ft_open(&cxt, dt_blob, max_size, max_find_device, platform_ops.realloc); diff --git a/arch/powerpc/boot/gunzip_util.c b/arch/powerpc/boot/gunzip_util.c new file mode 100644 index 0000000..df8ab07 --- /dev/null +++ b/arch/powerpc/boot/gunzip_util.c @@ -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; +} diff --git a/arch/powerpc/boot/gunzip_util.h b/arch/powerpc/boot/gunzip_util.h new file mode 100644 index 0000000..b3dfa6e --- /dev/null +++ b/arch/powerpc/boot/gunzip_util.h @@ -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_ */ diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c index 6f6b50d..56b56a8 100644 --- a/arch/powerpc/boot/main.c +++ b/arch/powerpc/boot/main.c @@ -14,11 +14,10 @@ #include "page.h" #include "string.h" #include "stdio.h" -#include "zlib.h" #include "ops.h" +#include "gunzip_util.h" #include "flatdevtree.h" - -extern void flush_cache(void *, unsigned long); +#include "reg.h" extern char _start[]; extern char __bss_start[]; @@ -30,304 +29,173 @@ extern char _initrd_end[]; extern char _dtb_start[]; extern char _dtb_end[]; +static struct gunzip_state gzstate; + struct addr_range { - unsigned long addr; + void *addr; unsigned long size; - unsigned long memsize; }; -static struct addr_range vmlinux; -static struct addr_range vmlinuz; -static struct addr_range initrd; - -static unsigned long elfoffset; -static int is_64bit; - -/* scratch space for gunzip; 46912 is from zlib_inflate_workspacesize() */ -static char scratch[46912]; -static char elfheader[256]; typedef void (*kernel_entry_t)(unsigned long, unsigned long, void *); #undef DEBUG -#define HEAD_CRC 2 -#define EXTRA_FIELD 4 -#define ORIG_NAME 8 -#define COMMENT 0x10 -#define RESERVED 0xe0 - -static void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) +static struct addr_range prep_kernel(void) { - 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(); - } + 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; - 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(); + /* gunzip the ELF header of the kernel */ + gunzip_start(&gzstate, vmlinuz_addr, vmlinuz_size); + gunzip_exactly(&gzstate, elfheader, sizeof(elfheader)); + + if (!parse_elf64(elfheader, &ei) && !parse_elf32(elfheader, &ei)) + fatal("Error: not a valid PPC32 or PPC64 ELF file!\n\r"); + + if (platform_ops.image_hdr) + platform_ops.image_hdr(elfheader); + + /* We need to alloc the memsize: gzip will expand the kernel + * text/data, then possible rubbish we don't care about. But + * the kernel bss must be claimed (it will be zero'd by the + * kernel itself) + */ + printf("Allocating 0x%lx bytes for kernel ...\n\r", ei.memsize); + + if (platform_ops.vmlinux_alloc) { + addr = platform_ops.vmlinux_alloc(ei.memsize); + } else { + if ((unsigned long)_start < ei.memsize) + fatal("Insufficient memory for kernel at address 0!" + " (_start=%p)\n\r", _start); } - *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; -} + /* 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); -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; + flush_cache(addr, ei.loadsize); + + return (struct addr_range){addr, ei.memsize}; } -static void prep_kernel(unsigned long a1, unsigned long a2) +static struct addr_range prep_initrd(struct addr_range vmlinux, void *chosen, + unsigned long initrd_addr, + unsigned long initrd_size) { - int len; - - vmlinuz.addr = (unsigned long)_vmlinux_start; - vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start); - - /* gunzip the ELF header of the kernel */ - if (*(unsigned short *)vmlinuz.addr == 0x1f8b) { - len = vmlinuz.size; - gunzip(elfheader, sizeof(elfheader), - (unsigned char *)vmlinuz.addr, &len); - } else - memcpy(elfheader, (const void *)vmlinuz.addr, - sizeof(elfheader)); - - if (!is_elf64(elfheader) && !is_elf32(elfheader)) { - printf("Error: not a valid PPC32 or PPC64 ELF file!\n\r"); - exit(); + /* 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 (platform_ops.image_hdr) - platform_ops.image_hdr(elfheader); - /* We need to alloc the memsize plus the file offset since gzip - * will expand the header (file offset), then the kernel, then - * possible rubbish we don't care about. But the kernel bss must - * be claimed (it will be zero'd by the kernel itself) - */ - printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux.memsize); - vmlinux.addr = (unsigned long)malloc(vmlinux.memsize); - if (vmlinux.addr == 0) { - printf("Can't allocate memory for kernel image !\n\r"); - exit(); - } + /* If there's no initrd at all, we're done */ + if (! initrd_size) + return (struct addr_range){0, 0}; /* - * Now find the initrd - * - * First see if we have an image attached to us. If so - * allocate memory for it and copy it there. + * If the initrd is too low it will be clobbered when the + * kernel relocates to its final location. In this case, + * allocate a safer place and move it. */ - initrd.size = (unsigned long)(_initrd_end - _initrd_start); - initrd.memsize = initrd.size; - if (initrd.size > 0) { + if (initrd_addr < vmlinux.size) { + void *old_addr = (void *)initrd_addr; + printf("Allocating 0x%lx bytes for initrd ...\n\r", - initrd.size); - initrd.addr = (unsigned long)malloc((u32)initrd.size); - if (initrd.addr == 0) { - printf("Can't allocate memory for initial " - "ramdisk !\n\r"); - exit(); - } - printf("initial ramdisk moving 0x%lx <- 0x%lx " - "(0x%lx bytes)\n\r", initrd.addr, - (unsigned long)_initrd_start, initrd.size); - memmove((void *)initrd.addr, (void *)_initrd_start, - initrd.size); - printf("initrd head: 0x%lx\n\r", - *((unsigned long *)initrd.addr)); - } else if (a2 != 0) { - /* Otherwise, see if yaboot or another loader gave us an initrd */ - initrd.addr = a1; - initrd.memsize = initrd.size = a2; - printf("Using loader supplied initrd at 0x%lx (0x%lx bytes)\n\r", - initrd.addr, initrd.size); + initrd_size); + initrd_addr = (unsigned long)malloc(initrd_size); + if (! initrd_addr) + fatal("Can't allocate memory for initial " + "ramdisk !\n\r"); + printf("Relocating initrd 0x%lx <- 0x%p (0x%lx bytes)\n\r", + initrd_addr, old_addr, initrd_size); + memmove((void *)initrd_addr, old_addr, initrd_size); } - /* Eventually gunzip the kernel */ - if (*(unsigned short *)vmlinuz.addr == 0x1f8b) { - printf("gunzipping (0x%lx <- 0x%lx:0x%0lx)...", - vmlinux.addr, vmlinuz.addr, vmlinuz.addr+vmlinuz.size); - len = vmlinuz.size; - gunzip((void *)vmlinux.addr, vmlinux.memsize, - (unsigned char *)vmlinuz.addr, &len); - printf("done 0x%lx bytes\n\r", len); - } else { - memmove((void *)vmlinux.addr,(void *)vmlinuz.addr, - vmlinuz.size); - } + printf("initrd head: 0x%lx\n\r", *((unsigned long *)initrd_addr)); - /* Skip over the ELF header */ -#ifdef DEBUG - printf("... skipping 0x%lx bytes of ELF header\n\r", - elfoffset); -#endif - vmlinux.addr += elfoffset; + /* Tell the kernel initrd address via device tree */ + setprop_val(chosen, "linux,initrd-start", (u32)(initrd_addr)); + setprop_val(chosen, "linux,initrd-end", (u32)(initrd_addr+initrd_size)); - flush_cache((void *)vmlinux.addr, vmlinux.size); + return (struct addr_range){(void *)initrd_addr, initrd_size}; } /* A buffer that may be edited by tools operating on a zImage binary so as to * edit the command line passed to vmlinux (by setting /chosen/bootargs). * The buffer is put in it's own section so that tools may locate it easier. */ -static char builtin_cmdline[COMMAND_LINE_SIZE] +static char cmdline[COMMAND_LINE_SIZE] __attribute__((__section__("__builtin_cmdline"))); -static void get_cmdline(char *buf, int size) +static void prep_cmdline(void *chosen) { - void *devp; - int len = strlen(builtin_cmdline); - - buf[0] = '\0'; - - if (len > 0) { /* builtin_cmdline overrides dt's /chosen/bootargs */ - len = min(len, size-1); - strncpy(buf, builtin_cmdline, len); - buf[len] = '\0'; - } - else if ((devp = finddevice("/chosen"))) - getprop(devp, "bootargs", buf, size); -} + if (cmdline[0] == '\0') + getprop(chosen, "bootargs", cmdline, COMMAND_LINE_SIZE-1); -static void set_cmdline(char *buf) -{ - void *devp; + 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 ((devp = finddevice("/chosen"))) - setprop(devp, "bootargs", buf, strlen(buf) + 1); + /* Put the command line back into the devtree for the kernel */ + setprop_str(chosen, "bootargs", cmdline); } struct platform_ops platform_ops; struct dt_ops dt_ops; struct console_ops console_ops; +struct loader_info loader_info; -void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) +void start(void) { + struct addr_range vmlinux, initrd; kernel_entry_t kentry; - char cmdline[COMMAND_LINE_SIZE]; unsigned long ft_addr = 0; + void *chosen; - memset(__bss_start, 0, _end - __bss_start); - memset(&platform_ops, 0, sizeof(platform_ops)); - memset(&dt_ops, 0, sizeof(dt_ops)); - memset(&console_ops, 0, sizeof(console_ops)); + /* Do this first, because malloc() could clobber the loader's + * command line. Only use the loader command line if a + * built-in command line wasn't set by an external tool */ + if ((loader_info.cmdline_len > 0) && (cmdline[0] == '\0')) + memmove(cmdline, loader_info.cmdline, + min(loader_info.cmdline_len, COMMAND_LINE_SIZE-1)); - if (platform_init(promptr, _dtb_start, _dtb_end)) - exit(); if (console_ops.open && (console_ops.open() < 0)) exit(); if (platform_ops.fixups) platform_ops.fixups(); printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", - _start, sp); + _start, get_sp()); - prep_kernel(a1, a2); + /* Ensure that the device tree has a /chosen node */ + chosen = finddevice("/chosen"); + if (!chosen) + chosen = create_node(NULL, "chosen"); - /* If cmdline came from zimage wrapper or if we can edit the one - * in the dt, print it out and edit it, if possible. - */ - if ((strlen(builtin_cmdline) > 0) || console_ops.edit_cmdline) { - get_cmdline(cmdline, COMMAND_LINE_SIZE); - printf("\n\rLinux/PowerPC load: %s", cmdline); - if (console_ops.edit_cmdline) - console_ops.edit_cmdline(cmdline, COMMAND_LINE_SIZE); - printf("\n\r"); - set_cmdline(cmdline); - } + vmlinux = prep_kernel(); + initrd = prep_initrd(vmlinux, chosen, + loader_info.initrd_addr, loader_info.initrd_size); + prep_cmdline(chosen); printf("Finalizing device tree..."); if (dt_ops.finalize) @@ -335,7 +203,7 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) if (ft_addr) printf(" flat tree at 0x%lx\n\r", ft_addr); else - printf(" using OF tree (promptr=%p)\n\r", promptr); + printf(" using OF tree (promptr=%p)\n\r", loader_info.promptr); if (console_ops.close) console_ops.close(); @@ -344,10 +212,9 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) if (ft_addr) kentry(ft_addr, 0, NULL); else - /* XXX initrd addr/size should be passed in properties */ - kentry(initrd.addr, initrd.size, promptr); + kentry((unsigned long)initrd.addr, initrd.size, + loader_info.promptr); - /* console closed so printf below may not work */ - printf("Error: Linux kernel returned to zImage boot wrapper!\n\r"); - exit(); + /* console closed so printf in fatal below may not work */ + fatal("Error: Linux kernel returned to zImage boot wrapper!\n\r"); } diff --git a/arch/powerpc/boot/ns16550.c b/arch/powerpc/boot/ns16550.c index 1ffe72e..f8f1b2f 100644 --- a/arch/powerpc/boot/ns16550.c +++ b/arch/powerpc/boot/ns16550.c @@ -55,10 +55,15 @@ static u8 ns16550_tstc(void) int ns16550_console_init(void *devp, struct serial_console_data *scdp) { int n; + unsigned long reg_phys; n = getprop(devp, "virtual-reg", ®_base, sizeof(reg_base)); - if (n != sizeof(reg_base)) - return -1; + if (n != sizeof(reg_base)) { + if (!dt_xlate_reg(devp, 0, ®_phys, NULL)) + return -1; + + reg_base = (void *)reg_phys; + } n = getprop(devp, "reg-shift", ®_shift, sizeof(reg_shift)); if (n != sizeof(reg_shift)) diff --git a/arch/powerpc/boot/of.c b/arch/powerpc/boot/of.c index 0182f38..d16ee3e 100644 --- a/arch/powerpc/boot/of.c +++ b/arch/powerpc/boot/of.c @@ -173,7 +173,7 @@ static void *claim(unsigned long virt, unsigned long size, unsigned long align) return (void *) virt; } -static void *of_try_claim(u32 size) +static void *of_try_claim(unsigned long size) { unsigned long addr = 0; @@ -208,6 +208,16 @@ static void of_image_hdr(const void *hdr) } } +static void *of_vmlinux_alloc(unsigned long size) +{ + void *p = malloc(size); + + if (!p) + fatal("Can't allocate memory for kernel image!\n\r"); + + return p; +} + static void of_exit(void) { call_prom("exit", 0, 0); @@ -256,11 +266,12 @@ static void of_console_write(char *buf, int len) call_prom("write", 3, 1, of_stdout_handle, buf, len); } -int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end) +void platform_init(unsigned long a1, unsigned long a2, void *promptr) { platform_ops.image_hdr = of_image_hdr; platform_ops.malloc = of_try_claim; platform_ops.exit = of_exit; + platform_ops.vmlinux_alloc = of_vmlinux_alloc; dt_ops.finddevice = of_finddevice; dt_ops.getprop = of_getprop; @@ -270,5 +281,9 @@ int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end) console_ops.write = of_console_write; prom = (int (*)(void *))promptr; - return 0; + loader_info.promptr = promptr; + if (a1 && a2 && a2 != 0xdeadbeef) { + loader_info.initrd_addr = a1; + loader_info.initrd_size = a2; + } } diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h index 8abb651..73bd47a 100644 --- a/arch/powerpc/boot/ops.h +++ b/arch/powerpc/boot/ops.h @@ -11,7 +11,9 @@ #ifndef _PPC_BOOT_OPS_H_ #define _PPC_BOOT_OPS_H_ +#include <stddef.h> #include "types.h" +#include "string.h" #define COMMAND_LINE_SIZE 512 #define MAX_PATH_LEN 256 @@ -21,10 +23,11 @@ struct platform_ops { void (*fixups)(void); void (*image_hdr)(const void *); - void * (*malloc)(u32 size); + void * (*malloc)(unsigned long size); void (*free)(void *ptr); void * (*realloc)(void *ptr, unsigned long size); void (*exit)(void); + void * (*vmlinux_alloc)(unsigned long size); }; extern struct platform_ops platform_ops; @@ -35,6 +38,12 @@ struct dt_ops { const int buflen); int (*setprop)(const void *phandle, const char *name, const void *buf, const int buflen); + void *(*get_parent)(const void *phandle); + /* The node must not already exist. */ + void *(*create_node)(const void *parent, const char *name); + void *(*find_node_by_prop_value)(const void *prev, + const char *propname, + const char *propval, int proplen); unsigned long (*finalize)(void); }; extern struct dt_ops dt_ops; @@ -58,13 +67,23 @@ struct serial_console_data { void (*close)(void); }; -int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end); +struct loader_info { + void *promptr; + unsigned long initrd_addr, initrd_size; + char *cmdline; + int cmdline_len; +}; +extern struct loader_info loader_info; + +void start(void); int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device); int serial_console_init(void); int ns16550_console_init(void *devp, struct serial_console_data *scdp); -void *simple_alloc_init(char *base, u32 heap_size, u32 granularity, - u32 max_allocs); - +void *simple_alloc_init(char *base, unsigned long heap_size, + unsigned long granularity, unsigned long max_allocs); +extern void flush_cache(void *, unsigned long); +int dt_xlate_reg(void *node, int res, unsigned long *addr, unsigned long *size); +int dt_xlate_addr(void *node, u32 *buf, int buflen, unsigned long *xlated_addr); static inline void *finddevice(const char *name) { @@ -76,12 +95,76 @@ static inline int getprop(void *devp, const char *name, void *buf, int buflen) return (dt_ops.getprop) ? dt_ops.getprop(devp, name, buf, buflen) : -1; } -static inline int setprop(void *devp, const char *name, void *buf, int buflen) +static inline int setprop(void *devp, const char *name, + const void *buf, int buflen) { return (dt_ops.setprop) ? dt_ops.setprop(devp, name, buf, buflen) : -1; } +#define setprop_val(devp, name, val) \ + do { \ + typeof(val) x = (val); \ + setprop((devp), (name), &x, sizeof(x)); \ + } while (0) + +static inline 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 *malloc(u32 size) +static inline void *find_node_by_prop_value(const void *prev, + const char *propname, + const char *propval, int proplen) +{ + if (dt_ops.find_node_by_prop_value) + return dt_ops.find_node_by_prop_value(prev, propname, + propval, proplen); + + return NULL; +} + +static inline void *find_node_by_prop_value_str(const void *prev, + const char *propname, + const char *propval) +{ + return find_node_by_prop_value(prev, propname, propval, + strlen(propval) + 1); +} + +static inline void *find_node_by_devtype(const void *prev, + const char *type) +{ + return find_node_by_prop_value_str(prev, "device_type", type); +} + +void dt_fixup_memory(u64 start, u64 size); +void dt_fixup_cpu_clocks(u32 cpufreq, u32 tbfreq, u32 busfreq); +void dt_fixup_clock(const char *path, u32 freq); +void __dt_fixup_mac_addresses(u32 startindex, ...); +#define dt_fixup_mac_addresses(...) \ + __dt_fixup_mac_addresses(0, __VA_ARGS__, NULL) + + +static inline void *find_node_by_linuxphandle(const u32 linuxphandle) +{ + return find_node_by_prop_value(NULL, "linux,phandle", + (char *)&linuxphandle, sizeof(u32)); +} + +static inline void *malloc(unsigned long size) { return (platform_ops.malloc) ? platform_ops.malloc(size) : NULL; } @@ -98,5 +181,11 @@ static inline void exit(void) platform_ops.exit(); for(;;); } +#define fatal(args...) { printf(args); exit(); } + + +#define BSS_STACK(size) \ + static char _bss_stack[size]; \ + void *_platform_stack_top = _bss_stack + sizeof(_bss_stack); #endif /* _PPC_BOOT_OPS_H_ */ diff --git a/arch/powerpc/boot/ppcboot.h b/arch/powerpc/boot/ppcboot.h new file mode 100644 index 0000000..5290ff2 --- /dev/null +++ b/arch/powerpc/boot/ppcboot.h @@ -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__ */ diff --git a/arch/powerpc/boot/reg.h b/arch/powerpc/boot/reg.h new file mode 100644 index 0000000..d3cd9ee --- /dev/null +++ b/arch/powerpc/boot/reg.h @@ -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 */ diff --git a/arch/powerpc/boot/simple_alloc.c b/arch/powerpc/boot/simple_alloc.c index cfe3a75..65ec135 100644 --- a/arch/powerpc/boot/simple_alloc.c +++ b/arch/powerpc/boot/simple_alloc.c @@ -19,24 +19,24 @@ #define ENTRY_IN_USE 0x02 static struct alloc_info { - u32 flags; - u32 base; - u32 size; + unsigned long flags; + unsigned long base; + unsigned long size; } *alloc_tbl; -static u32 tbl_entries; -static u32 alloc_min; -static u32 next_base; -static u32 space_left; +static unsigned long tbl_entries; +static unsigned long alloc_min; +static unsigned long next_base; +static unsigned long space_left; /* * First time an entry is used, its base and size are set. * An entry can be freed and re-malloc'd but its base & size don't change. * Should be smart enough for needs of bootwrapper. */ -static void *simple_malloc(u32 size) +static void *simple_malloc(unsigned long size) { - u32 i; + unsigned long i; struct alloc_info *p = alloc_tbl; if (size == 0) @@ -67,13 +67,14 @@ err_out: static struct alloc_info *simple_find_entry(void *ptr) { - u32 i; + unsigned long i; struct alloc_info *p = alloc_tbl; for (i=0; i<tbl_entries; i++,p++) { if (!(p->flags & ENTRY_BEEN_USED)) break; - if ((p->flags & ENTRY_IN_USE) && (p->base == (u32)ptr)) + if ((p->flags & ENTRY_IN_USE) && + (p->base == (unsigned long)ptr)) return p; } return NULL; @@ -122,10 +123,10 @@ static void *simple_realloc(void *ptr, unsigned long size) * Returns addr of first byte after heap so caller can see if it took * too much space. If so, change args & try again. */ -void *simple_alloc_init(char *base, u32 heap_size, u32 granularity, - u32 max_allocs) +void *simple_alloc_init(char *base, unsigned long heap_size, + unsigned long granularity, unsigned long max_allocs) { - u32 heap_base, tbl_size; + unsigned long heap_base, tbl_size; heap_size = _ALIGN_UP(heap_size, granularity); alloc_min = granularity; @@ -136,7 +137,7 @@ void *simple_alloc_init(char *base, u32 heap_size, u32 granularity, alloc_tbl = (struct alloc_info *)_ALIGN_UP((unsigned long)base, 8); memset(alloc_tbl, 0, tbl_size); - heap_base = _ALIGN_UP((u32)alloc_tbl + tbl_size, alloc_min); + heap_base = _ALIGN_UP((unsigned long)alloc_tbl + tbl_size, alloc_min); next_base = heap_base; space_left = heap_size; diff --git a/arch/powerpc/boot/stdio.h b/arch/powerpc/boot/stdio.h index 73b8a91..adffc58 100644 --- a/arch/powerpc/boot/stdio.h +++ b/arch/powerpc/boot/stdio.h @@ -7,11 +7,12 @@ #define EINVAL 22 /* Invalid argument */ #define ENOSPC 28 /* No space left on device */ -extern int printf(const char *fmt, ...); +extern int printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); #define fprintf(fmt, args...) printf(args) -extern int sprintf(char *buf, const char *fmt, ...); +extern int sprintf(char *buf, const char *fmt, ...) + __attribute__((format(printf, 2, 3))); extern int vsprintf(char *buf, const char *fmt, va_list args); diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper index 024e4d4..5cedd90 100755 --- a/arch/powerpc/boot/wrapper +++ b/arch/powerpc/boot/wrapper @@ -29,6 +29,7 @@ initrd= dtb= dts= cacheit= +gzip=.gz # cross-compilation prefix CROSS= @@ -42,7 +43,7 @@ tmpdir=. usage() { echo 'Usage: wrapper [-o output] [-p platform] [-i initrd]' >&2 echo ' [-d devtree] [-s tree.dts] [-c] [-C cross-prefix]' >&2 - echo ' [-D datadir] [-W workingdir] [vmlinux]' >&2 + echo ' [-D datadir] [-W workingdir] [--no-gzip] [vmlinux]' >&2 exit 1 } @@ -91,6 +92,9 @@ while [ "$#" -gt 0 ]; do [ "$#" -gt 0 ] || usage tmpdir="$1" ;; + --no-gzip) + gzip= + ;; -?) usage ;; @@ -137,31 +141,44 @@ miboot|uboot) ksection=image isection=initrd ;; +cuboot*) + gzip= + ;; esac vmz="$tmpdir/`basename \"$kernel\"`.$ext" -if [ -z "$cacheit" -o ! -f "$vmz.gz" -o "$vmz.gz" -ot "$kernel" ]; then +if [ -z "$cacheit" -o ! -f "$vmz$gzip" -o "$vmz$gzip" -ot "$kernel" ]; then ${CROSS}objcopy $objflags "$kernel" "$vmz.$$" - gzip -f -9 "$vmz.$$" + + if [ -n "$gzip" ]; then + gzip -f -9 "$vmz.$$" + fi + if [ -n "$cacheit" ]; then - mv -f "$vmz.$$.gz" "$vmz.gz" + mv -f "$vmz.$$$gzip" "$vmz$gzip" else vmz="$vmz.$$" fi fi +vmz="$vmz$gzip" + case "$platform" in -uboot) - rm -f "$ofile" +uboot|cuboot*) version=`${CROSS}strings "$kernel" | grep '^Linux version [-0-9.]' | \ cut -d' ' -f3` if [ -n "$version" ]; then version="-n Linux-$version" fi +esac + +case "$platform" in +uboot) + rm -f "$ofile" mkimage -A ppc -O linux -T kernel -C gzip -a 00000000 -e 00000000 \ - $version -d "$vmz.gz" "$ofile" + $version -d "$vmz" "$ofile" if [ -z "$cacheit" ]; then - rm -f $vmz.gz + rm -f "$vmz" fi exit 0 ;; @@ -173,9 +190,9 @@ addsec() { --set-section-flags=$3=contents,alloc,load,readonly,data } -addsec $tmp "$vmz.gz" $ksection $object/empty.o +addsec $tmp "$vmz" $ksection $object/empty.o if [ -z "$cacheit" ]; then - rm -f "$vmz.gz" + rm -f "$vmz" fi if [ -n "$initrd" ]; then @@ -191,7 +208,7 @@ fi if [ "$platform" != "miboot" ]; then ${CROSS}ld -m elf32ppc -T $lds -o "$ofile" \ - $object/crt0.o $platformo $tmp $object/wrapper.a + $platformo $tmp $object/wrapper.a rm $tmp fi @@ -201,7 +218,19 @@ pseries|chrp) $object/addnote "$ofile" ;; pmaccoff) - ${CROSS}objcopy -O aixcoff-rs6000 --set-start 0x500000 "$ofile" + entry=`objdump -f "$ofile" | grep '^start address ' | \ + cut -d' ' -f3` + ${CROSS}objcopy -O aixcoff-rs6000 --set-start "$entry" "$ofile" $object/hack-coff "$ofile" ;; +cuboot*) + base=`${CROSS}nm "$ofile" | grep ' _start$' | cut -d' ' -f1` + entry=`${CROSS}objdump -f "$ofile" | grep '^start address ' | \ + cut -d' ' -f3` + mv "$ofile" "$ofile".elf + ${CROSS}objcopy -O binary "$ofile".elf "$ofile".bin + gzip -f -9 "$ofile".bin + mkimage -A ppc -O linux -T kernel -C gzip -a "$base" -e "$entry" \ + $version -d "$ofile".bin.gz "$ofile" + ;; esac diff --git a/arch/powerpc/boot/zImage.coff.lds.S b/arch/powerpc/boot/zImage.coff.lds.S index a360905..fe87a90 100644 --- a/arch/powerpc/boot/zImage.coff.lds.S +++ b/arch/powerpc/boot/zImage.coff.lds.S @@ -1,5 +1,6 @@ OUTPUT_ARCH(powerpc:common) -ENTRY(_start) +ENTRY(_zimage_start_opd) +EXTERN(_zimage_start_opd) SECTIONS { . = (5*1024*1024); diff --git a/arch/powerpc/boot/zImage.lds.S b/arch/powerpc/boot/zImage.lds.S index 4be3c64..f6e380f 100644 --- a/arch/powerpc/boot/zImage.lds.S +++ b/arch/powerpc/boot/zImage.lds.S @@ -1,5 +1,6 @@ OUTPUT_ARCH(powerpc:common) ENTRY(_zimage_start) +EXTERN(_zimage_start) SECTIONS { . = (4*1024*1024); diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig index cf7e316..6061e5f 100644 --- a/arch/powerpc/configs/cell_defconfig +++ b/arch/powerpc/configs/cell_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.21-rc3 -# Fri Mar 9 23:34:53 2007 +# Linux kernel version: 2.6.21-rc6 +# Mon Apr 23 20:46:48 2007 # CONFIG_PPC64=y CONFIG_64BIT=y @@ -139,11 +139,31 @@ CONFIG_PPC_MULTIPLATFORM=y # CONFIG_PPC_PMAC is not set # CONFIG_PPC_MAPLE is not set # CONFIG_PPC_PASEMI is not set +CONFIG_PPC_CELLEB=y +CONFIG_PPC_PS3=y + +# +# PS3 Platform Options +# +# CONFIG_PS3_ADVANCED is not set +CONFIG_PS3_HTAB_SIZE=20 +# CONFIG_PS3_DYNAMIC_DMA is not set +CONFIG_PS3_USE_LPAR_ADDR=y +CONFIG_PS3_VUART=y +CONFIG_PS3_PS3AV=y +CONFIG_PS3_SYS_MANAGER=y CONFIG_PPC_CELL=y CONFIG_PPC_CELL_NATIVE=y CONFIG_PPC_IBM_CELL_BLADE=y -CONFIG_PPC_PS3=y -CONFIG_PPC_CELLEB=y + +# +# Cell Broadband Engine options +# +CONFIG_SPU_FS=m +CONFIG_SPU_BASE=y +CONFIG_CBE_RAS=y +CONFIG_CBE_THERM=m +CONFIG_CBE_CPUFREQ=m CONFIG_PPC_NATIVE=y CONFIG_UDBG_RTAS_CONSOLE=y CONFIG_PPC_UDBG_BEAT=y @@ -175,26 +195,6 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=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 # # CONFIG_HZ_100 is not set @@ -534,7 +534,6 @@ CONFIG_BLK_DEV_GENERIC=y # CONFIG_BLK_DEV_OPTI621 is not set CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_IDEDMA_ONLYDISK is not set CONFIG_BLK_DEV_AEC62XX=y # CONFIG_BLK_DEV_ALI15X3 is not set @@ -561,11 +560,10 @@ CONFIG_BLK_DEV_SIIMAGE=y # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set # CONFIG_BLK_DEV_TC86C001 is not set -CONFIG_BLK_DEV_IDE_CELLEB=y +CONFIG_BLK_DEV_CELLEB=y # CONFIG_IDE_ARM is not set CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_IVB is not set -CONFIG_IDEDMA_AUTO=y # CONFIG_BLK_DEV_HD is not set # @@ -937,7 +935,7 @@ CONFIG_UNIX98_PTYS=y # CONFIG_LEGACY_PTYS is not set CONFIG_HVC_DRIVER=y CONFIG_HVC_RTAS=y -# CONFIG_HVC_BEAT is not set +CONFIG_HVC_BEAT=y # # IPMI @@ -1482,6 +1480,8 @@ CONFIG_NLS_ISO8859_15=m # Distributed Lock Manager # # CONFIG_DLM is not set +# CONFIG_UCC_SLOW is not set +# CONFIG_UCC_FAST is not set # # Library routines @@ -1540,6 +1540,7 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_FAULT_INJECTION is not set # CONFIG_DEBUG_STACKOVERFLOW is not set # CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_PAGEALLOC is not set CONFIG_DEBUGGER=y CONFIG_XMON=y CONFIG_XMON_DEFAULT=y diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig index 7724847..3ccf19d 100644 --- a/arch/powerpc/configs/g5_defconfig +++ b/arch/powerpc/configs/g5_defconfig @@ -143,7 +143,7 @@ CONFIG_PPC_NATIVE=y CONFIG_U3_DART=y # CONFIG_PPC_RTAS is not set # CONFIG_MMIO_NVRAM is not set -CONFIG_MPIC_BROKEN_U3=y +CONFIG_MPIC_U3_HT_IRQS=y # CONFIG_PPC_MPC106 is not set CONFIG_PPC_970_NAP=y # CONFIG_PPC_INDIRECT_IO is not set diff --git a/arch/powerpc/configs/maple_defconfig b/arch/powerpc/configs/maple_defconfig index de97f2f..15366f0 100644 --- a/arch/powerpc/configs/maple_defconfig +++ b/arch/powerpc/configs/maple_defconfig @@ -146,7 +146,7 @@ CONFIG_PPC_RTAS=y CONFIG_RTAS_PROC=y # CONFIG_RTAS_FLASH is not set # CONFIG_MMIO_NVRAM is not set -CONFIG_MPIC_BROKEN_U3=y +CONFIG_MPIC_U3_HT_IRQS=y # CONFIG_PPC_MPC106 is not set CONFIG_PPC_970_NAP=y # CONFIG_PPC_INDIRECT_IO is not set diff --git a/arch/powerpc/configs/mpc832x_rdb_defconfig b/arch/powerpc/configs/mpc832x_rdb_defconfig new file mode 100644 index 0000000..56fc0a8 --- /dev/null +++ b/arch/powerpc/configs/mpc832x_rdb_defconfig @@ -0,0 +1,1292 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.21-rc3 +# Mon Mar 12 17:32:19 2007 +# +# CONFIG_PPC64 is not set +CONFIG_PPC32=y +CONFIG_PPC_MERGE=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_IRQ_PER_CPU=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_ARCH_HAS_ILOG2_U32=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_PPC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +CONFIG_PPC_UDBG_16550=y +# CONFIG_GENERIC_TBSYNC is not set +CONFIG_AUDIT_ARCH=y +CONFIG_GENERIC_BUG=y +CONFIG_DEFAULT_UIMAGE=y + +# +# Processor support +# +# CONFIG_CLASSIC32 is not set +# CONFIG_PPC_82xx is not set +CONFIG_PPC_83xx=y +# CONFIG_PPC_85xx is not set +# CONFIG_PPC_86xx is not set +# CONFIG_PPC_8xx is not set +# CONFIG_40x is not set +# CONFIG_44x is not set +# CONFIG_E200 is not set +CONFIG_6xx=y +CONFIG_83xx=y +CONFIG_PPC_FPU=y +# CONFIG_PPC_DCR_NATIVE is not set +# CONFIG_PPC_DCR_MMIO is not set +CONFIG_PPC_STD_MMU=y +CONFIG_PPC_STD_MMU_32=y +# CONFIG_SMP is not set +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_IPC_NS is not set +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_UTS_NS is not set +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +CONFIG_SYSFS_DEPRECATED=y +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_SYSCTL_SYSCALL=y +# CONFIG_KALLSYMS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +# CONFIG_EPOLL is not set +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_KMOD is not set + +# +# Block layer +# +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_QUICC_ENGINE=y +CONFIG_PPC_GEN550=y +# CONFIG_WANT_EARLY_SERIAL is not set + +# +# Platform support +# +# CONFIG_MPC8313_RDB is not set +# CONFIG_MPC832x_MDS is not set +CONFIG_MPC832x_RDB=y +# CONFIG_MPC834x_MDS is not set +# CONFIG_MPC834x_ITX is not set +# CONFIG_MPC836x_MDS is not set +CONFIG_PPC_MPC832x=y +# CONFIG_MPIC is not set + +# +# Kernel options +# +# CONFIG_HIGHMEM is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_MATH_EMULATION=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set +# CONFIG_PM is not set +CONFIG_SECCOMP=y +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_ZONE_DMA=y +CONFIG_GENERIC_ISA_DMA=y +# CONFIG_MPIC_WEIRD is not set +# CONFIG_PPC_I8259 is not set +CONFIG_PPC_INDIRECT_PCI=y +CONFIG_FSL_SOC=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +# CONFIG_PCIEPORTBUS is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Advanced setup +# +# CONFIG_ADVANCED_OPTIONS is not set + +# +# Default settings for advanced configuration options are used +# +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_KERNEL_START=0xc0000000 +CONFIG_TASK_SIZE=0x80000000 +CONFIG_BOOT_LOAD=0x00800000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNPACPI is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=32768 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# Misc devices +# +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set + +# +# SCSI low-level drivers +# +# CONFIG_ISCSI_TCP is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_ARCMSR is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_STEX is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_QLA_ISCSI is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_SRP is not set + +# +# Serial ATA (prod) and Parallel ATA (experimental) drivers +# +# CONFIG_ATA is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set +# CONFIG_FUSION_SPI is not set +# CONFIG_FUSION_FC is not set +# CONFIG_FUSION_SAS is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# +# CONFIG_MAC_EMUMOUSEBTN is not set +# CONFIG_WINDFARM is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +CONFIG_E1000=y +# CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set +# CONFIG_GIANFAR is not set +CONFIG_UCC_GETH=y +CONFIG_UGETH_NAPI=y +# CONFIG_UGETH_MAGIC_PACKET is not set +# CONFIG_UGETH_FILTERING is not set +# CONFIG_UGETH_TX_ON_DEMOND is not set +# CONFIG_QLA3XXX is not set +# CONFIG_ATL1 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_CHELSIO_T3 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set +# CONFIG_MYRI10GE is not set +# CONFIG_NETXEN_NIC is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_UARTLITE is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_OF_PLATFORM is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_83xx_WDT=y + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_HW_RANDOM=y +# CONFIG_NVRAM is not set +CONFIG_GEN_RTC=y +# CONFIG_GEN_RTC_X is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +CONFIG_I2C_MPC=y +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PASEMI is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_M41T00 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ABITUGURU is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_SM501 is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set + +# +# Graphics support +# +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_FB is not set +# CONFIG_FB_IBM_GXT4500 is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# HID Devices +# +CONFIG_HID=y +# CONFIG_HID_DEBUG is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_SPLIT_ISO is not set +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PPC_OF=y +CONFIG_USB_OHCI_HCD_PPC_OF_BE=y +# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set +CONFIG_USB_OHCI_HCD_PCI=y +CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y +CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Input Devices +# +# CONFIG_USB_HID is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_TOUCHSCREEN is not set +# CONFIG_USB_YEALINK is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set +# CONFIG_USB_ATI_REMOTE2 is not set +# CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set +# CONFIG_USB_GTCO is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET_MII is not set +# CONFIG_USB_USBNET is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +# CONFIG_RTC_CLASS is not set + +# +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients +# + +# +# DMA Devices +# + +# +# Auxiliary Display support +# + +# +# Virtualization +# + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4DEV_FS is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +CONFIG_LDM_PARTITION=y +# CONFIG_LDM_DEBUG is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +CONFIG_NLS_CODEPAGE_932=y +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +CONFIG_NLS_ISO8859_8=y +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Distributed Lock Manager +# +# CONFIG_DLM is not set + +# +# QE Options +# +CONFIG_UCC_SLOW=y +CONFIG_UCC_FAST=y +CONFIG_UCC=y + +# +# Library routines +# +CONFIG_BITREVERSE=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y + +# +# Instrumentation Support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_MUST_CHECK=y +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_BOOTX_TEXT is not set +# CONFIG_SERIAL_TEXT_DEBUG is not set +# CONFIG_PPC_EARLY_DEBUG is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_MANAGER=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_GF128MUL is not set +CONFIG_CRYPTO_ECB=m +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_PCBC=m +# CONFIG_CRYPTO_LRW is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# diff --git a/arch/powerpc/configs/mpc8544_ds_defconfig b/arch/powerpc/configs/mpc8544_ds_defconfig new file mode 100644 index 0000000..b563513 --- /dev/null +++ b/arch/powerpc/configs/mpc8544_ds_defconfig @@ -0,0 +1,1077 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.21-rc3 +# Mon Mar 19 17:18:49 2007 +# +# CONFIG_PPC64 is not set +CONFIG_PPC32=y +CONFIG_PPC_MERGE=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_IRQ_PER_CPU=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_ARCH_HAS_ILOG2_U32=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_PPC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +CONFIG_PPC_UDBG_16550=y +# CONFIG_GENERIC_TBSYNC is not set +CONFIG_AUDIT_ARCH=y +CONFIG_GENERIC_BUG=y +CONFIG_DEFAULT_UIMAGE=y + +# +# Processor support +# +# CONFIG_CLASSIC32 is not set +# CONFIG_PPC_82xx is not set +# CONFIG_PPC_83xx is not set +CONFIG_PPC_85xx=y +# CONFIG_PPC_86xx is not set +# CONFIG_PPC_8xx is not set +# CONFIG_40x is not set +# CONFIG_44x is not set +# CONFIG_E200 is not set +CONFIG_85xx=y +CONFIG_E500=y +# CONFIG_PPC_DCR_NATIVE is not set +# CONFIG_PPC_DCR_MMIO is not set +CONFIG_BOOKE=y +CONFIG_FSL_BOOKE=y +# CONFIG_PHYS_64BIT is not set +# CONFIG_SPE is not set +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_IPC_NS=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +# CONFIG_TASKSTATS is not set +# CONFIG_UTS_NS is not set +CONFIG_AUDIT=y +# CONFIG_AUDITSYSCALL is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_SYSFS_DEPRECATED=y +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +# CONFIG_HOTPLUG is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# Block layer +# +CONFIG_BLOCK=y +CONFIG_LBD=y +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_WANT_EARLY_SERIAL is not set + +# +# Platform support +# +# CONFIG_MPC8540_ADS is not set +# CONFIG_MPC8560_ADS is not set +# CONFIG_MPC85xx_CDS is not set +# CONFIG_MPC85xx_MDS is not set +CONFIG_MPC8544_DS=y +CONFIG_MPC85xx=y +CONFIG_PPC_INDIRECT_PCI_BE=y +CONFIG_MPIC=y + +# +# Kernel options +# +CONFIG_HIGHMEM=y +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=m +CONFIG_MATH_EMULATION=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_PROC_DEVICETREE=y +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="root=/dev/sda3 rw console=ttyS0,115200" +# CONFIG_PM is not set +CONFIG_SECCOMP=y +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_ZONE_DMA=y +# CONFIG_MPIC_WEIRD is not set +# CONFIG_PPC_I8259 is not set +CONFIG_PPC_INDIRECT_PCI=y +CONFIG_FSL_SOC=y +# CONFIG_PCI is not set +# CONFIG_PCI_DOMAINS is not set + +# +# PCCARD (PCMCIA/CardBus) support +# + +# +# PCI Hotplug Support +# + +# +# Advanced setup +# +# CONFIG_ADVANCED_OPTIONS is not set + +# +# Default settings for advanced configuration options are used +# +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_KERNEL_START=0xc0000000 +CONFIG_TASK_SIZE=0x80000000 +CONFIG_BOOT_LOAD=0x00800000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=m +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +CONFIG_NET_KEY=m +# CONFIG_NET_KEY_MIGRATE is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +CONFIG_NET_IPIP=y +CONFIG_NET_IPGRE=y +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_ARPD=y +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +CONFIG_INET_TUNNEL=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set +CONFIG_FIB_RULES=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNPACPI is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_NBD=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=2 +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# Misc devices +# + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=y +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +CONFIG_SCSI_LOGGING=y +# CONFIG_SCSI_SCAN_ASYNC is not set + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set + +# +# SCSI low-level drivers +# +# CONFIG_ISCSI_TCP is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Serial ATA (prod) and Parallel ATA (experimental) drivers +# +CONFIG_ATA=y +# CONFIG_ATA_NONSTANDARD is not set +# CONFIG_PATA_PLATFORM is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Macintosh device drivers +# +# CONFIG_MAC_EMUMOUSEBTN is not set +# CONFIG_WINDFARM is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# PHY device support +# +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +CONFIG_VITESSE_PHY=y +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_FIXED_PHY is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y + +# +# Ethernet (1000 Mbit) +# +CONFIG_GIANFAR=y +CONFIG_GFAR_NAPI=y + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_UARTLITE is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_OF_PLATFORM is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_HW_RANDOM is not set +CONFIG_NVRAM=y +CONFIG_GEN_RTC=y +CONFIG_GEN_RTC_X=y +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +# CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_SM501 is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +CONFIG_DVB=y +CONFIG_DVB_CORE=m +# CONFIG_DVB_CORE_ATTACH is not set + +# +# Supported DVB Frontends +# + +# +# Customise DVB Frontends +# +# CONFIG_DVB_FE_CUSTOMISE is not set + +# +# DVB-S (satellite) frontends +# + +# +# DVB-T (terrestrial) frontends +# + +# +# DVB-C (cable) frontends +# + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# + +# +# Tuners/PLL support +# + +# +# Miscellaneous devices +# + +# +# Graphics support +# +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_FB is not set +# CONFIG_FB_IBM_GXT4500 is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# HID Devices +# +CONFIG_HID=y +# CONFIG_HID_DEBUG is not set + +# +# USB support +# +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# InfiniBand support +# + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set + +# +# RTC drivers +# +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_TEST is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients +# + +# +# DMA Devices +# + +# +# Auxiliary Display support +# + +# +# Virtualization +# + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4DEV_FS is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +CONFIG_NTFS_FS=y +# CONFIG_NTFS_DEBUG is not set +# CONFIG_NTFS_RW is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +CONFIG_ADFS_FS=m +# CONFIG_ADFS_FS_RW is not set +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +CONFIG_CRAMFS=y +CONFIG_VXFS_FS=m +CONFIG_HPFS_FS=m +CONFIG_QNX4FS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=m + +# +# Distributed Lock Manager +# +# CONFIG_DLM is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y + +# +# Instrumentation Support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_MUST_CHECK=y +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_HIGHMEM is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_LIST is not set +CONFIG_FORCED_INLINING=y +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_DEBUG_STACKOVERFLOW is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUGGER is not set +# CONFIG_BDI_SWITCH is not set +# CONFIG_BOOTX_TEXT is not set +# CONFIG_PPC_EARLY_DEBUG is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_ECB is not set +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_PCBC=m +# CONFIG_CRYPTO_LRW is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig index a8da0ae..126b9f8 100644 --- a/arch/powerpc/configs/ppc64_defconfig +++ b/arch/powerpc/configs/ppc64_defconfig @@ -152,7 +152,7 @@ CONFIG_RTAS_ERROR_LOGGING=y CONFIG_RTAS_PROC=y CONFIG_RTAS_FLASH=m CONFIG_MMIO_NVRAM=y -CONFIG_MPIC_BROKEN_U3=y +CONFIG_MPIC_U3_HT_IRQS=y CONFIG_IBMVIO=y # CONFIG_IBMEBUS is not set # CONFIG_PPC_MPC106 is not set diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 8120d42..e0fa80ec 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -25,8 +25,8 @@ obj-$(CONFIG_PPC_970_NAP) += idle_power4.o obj-$(CONFIG_PPC_OF) += of_device.o of_platform.o prom_parse.o procfs-$(CONFIG_PPC64) := proc_ppc64.o obj-$(CONFIG_PROC_FS) += $(procfs-y) -rtaspci-$(CONFIG_PPC64) := rtas_pci.o -obj-$(CONFIG_PPC_RTAS) += rtas.o rtas-rtc.o $(rtaspci-y) +rtaspci-$(CONFIG_PPC64)-$(CONFIG_PCI) := rtas_pci.o +obj-$(CONFIG_PPC_RTAS) += rtas.o rtas-rtc.o $(rtaspci-y-y) obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o obj-$(CONFIG_RTAS_PROC) += rtas-proc.o obj-$(CONFIG_LPARCFG) += lparcfg.o diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c index 4734b5d..5c9ff7f 100644 --- a/arch/powerpc/kernel/align.c +++ b/arch/powerpc/kernel/align.c @@ -241,7 +241,7 @@ static int emulate_dcbz(struct pt_regs *regs, unsigned char __user *addr) if (user_mode(regs) && !access_ok(VERIFY_WRITE, p, size)) return -EFAULT; for (i = 0; i < size / sizeof(long); ++i) - if (__put_user(0, p+i)) + if (__put_user_inatomic(0, p+i)) return -EFAULT; return 1; } @@ -288,7 +288,8 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr, } else { unsigned long pc = regs->nip ^ (swiz & 4); - if (__get_user(instr, (unsigned int __user *)pc)) + if (__get_user_inatomic(instr, + (unsigned int __user *)pc)) return -EFAULT; if (swiz == 0 && (flags & SW)) instr = cpu_to_le32(instr); @@ -324,27 +325,31 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr, ((nb0 + 3) / 4) * sizeof(unsigned long)); for (i = 0; i < nb; ++i, ++p) - if (__get_user(REG_BYTE(rptr, i ^ bswiz), SWIZ_PTR(p))) + if (__get_user_inatomic(REG_BYTE(rptr, i ^ bswiz), + SWIZ_PTR(p))) return -EFAULT; if (nb0 > 0) { rptr = ®s->gpr[0]; addr += nb; for (i = 0; i < nb0; ++i, ++p) - if (__get_user(REG_BYTE(rptr, i ^ bswiz), - SWIZ_PTR(p))) + if (__get_user_inatomic(REG_BYTE(rptr, + i ^ bswiz), + SWIZ_PTR(p))) return -EFAULT; } } else { for (i = 0; i < nb; ++i, ++p) - if (__put_user(REG_BYTE(rptr, i ^ bswiz), SWIZ_PTR(p))) + if (__put_user_inatomic(REG_BYTE(rptr, i ^ bswiz), + SWIZ_PTR(p))) return -EFAULT; if (nb0 > 0) { rptr = ®s->gpr[0]; addr += nb; for (i = 0; i < nb0; ++i, ++p) - if (__put_user(REG_BYTE(rptr, i ^ bswiz), - SWIZ_PTR(p))) + if (__put_user_inatomic(REG_BYTE(rptr, + i ^ bswiz), + SWIZ_PTR(p))) return -EFAULT; } } @@ -398,7 +403,8 @@ int fix_alignment(struct pt_regs *regs) if (cpu_has_feature(CPU_FTR_PPC_LE) && (regs->msr & MSR_LE)) pc ^= 4; - if (unlikely(__get_user(instr, (unsigned int __user *)pc))) + if (unlikely(__get_user_inatomic(instr, + (unsigned int __user *)pc))) return -EFAULT; if (cpu_has_feature(CPU_FTR_REAL_LE) && (regs->msr & MSR_LE)) instr = cpu_to_le32(instr); @@ -474,16 +480,16 @@ int fix_alignment(struct pt_regs *regs) p = (unsigned long) addr; switch (nb) { case 8: - ret |= __get_user(data.v[0], SWIZ_PTR(p++)); - ret |= __get_user(data.v[1], SWIZ_PTR(p++)); - ret |= __get_user(data.v[2], SWIZ_PTR(p++)); - ret |= __get_user(data.v[3], SWIZ_PTR(p++)); + ret |= __get_user_inatomic(data.v[0], SWIZ_PTR(p++)); + ret |= __get_user_inatomic(data.v[1], SWIZ_PTR(p++)); + ret |= __get_user_inatomic(data.v[2], SWIZ_PTR(p++)); + ret |= __get_user_inatomic(data.v[3], SWIZ_PTR(p++)); case 4: - ret |= __get_user(data.v[4], SWIZ_PTR(p++)); - ret |= __get_user(data.v[5], SWIZ_PTR(p++)); + ret |= __get_user_inatomic(data.v[4], SWIZ_PTR(p++)); + ret |= __get_user_inatomic(data.v[5], SWIZ_PTR(p++)); case 2: - ret |= __get_user(data.v[6], SWIZ_PTR(p++)); - ret |= __get_user(data.v[7], SWIZ_PTR(p++)); + ret |= __get_user_inatomic(data.v[6], SWIZ_PTR(p++)); + ret |= __get_user_inatomic(data.v[7], SWIZ_PTR(p++)); if (unlikely(ret)) return -EFAULT; } @@ -551,16 +557,16 @@ int fix_alignment(struct pt_regs *regs) p = (unsigned long) addr; switch (nb) { case 8: - ret |= __put_user(data.v[0], SWIZ_PTR(p++)); - ret |= __put_user(data.v[1], SWIZ_PTR(p++)); - ret |= __put_user(data.v[2], SWIZ_PTR(p++)); - ret |= __put_user(data.v[3], SWIZ_PTR(p++)); + ret |= __put_user_inatomic(data.v[0], SWIZ_PTR(p++)); + ret |= __put_user_inatomic(data.v[1], SWIZ_PTR(p++)); + ret |= __put_user_inatomic(data.v[2], SWIZ_PTR(p++)); + ret |= __put_user_inatomic(data.v[3], SWIZ_PTR(p++)); case 4: - ret |= __put_user(data.v[4], SWIZ_PTR(p++)); - ret |= __put_user(data.v[5], SWIZ_PTR(p++)); + ret |= __put_user_inatomic(data.v[4], SWIZ_PTR(p++)); + ret |= __put_user_inatomic(data.v[5], SWIZ_PTR(p++)); case 2: - ret |= __put_user(data.v[6], SWIZ_PTR(p++)); - ret |= __put_user(data.v[7], SWIZ_PTR(p++)); + ret |= __put_user_inatomic(data.v[6], SWIZ_PTR(p++)); + ret |= __put_user_inatomic(data.v[7], SWIZ_PTR(p++)); } if (unlikely(ret)) return -EFAULT; diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 030d300..0c5150c 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -77,7 +77,6 @@ int main(void) DEFINE(KSP_VSID, offsetof(struct thread_struct, ksp_vsid)); #else /* CONFIG_PPC64 */ DEFINE(PGDIR, offsetof(struct thread_struct, pgdir)); - DEFINE(LAST_SYSCALL, offsetof(struct thread_struct, last_syscall)); #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) DEFINE(THREAD_DBCR0, offsetof(struct thread_struct, dbcr0)); DEFINE(PT_PTRACED, PT_PTRACED); @@ -140,6 +139,7 @@ int main(void) DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time)); DEFINE(PACA_SLBSHADOWPTR, offsetof(struct paca_struct, slb_shadow_ptr)); DEFINE(PACA_DATA_OFFSET, offsetof(struct paca_struct, data_offset)); + DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save)); DEFINE(SLBSHADOW_STACKVSID, offsetof(struct slb_shadow, save_area[SLB_NUM_BOLTED - 1].vsid)); diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c index 3678997..e7b6846 100644 --- a/arch/powerpc/kernel/btext.c +++ b/arch/powerpc/kernel/btext.c @@ -161,33 +161,33 @@ int btext_initialize(struct device_node *np) unsigned long address = 0; const u32 *prop; - prop = get_property(np, "linux,bootx-width", NULL); + prop = of_get_property(np, "linux,bootx-width", NULL); if (prop == NULL) - prop = get_property(np, "width", NULL); + prop = of_get_property(np, "width", NULL); if (prop == NULL) return -EINVAL; width = *prop; - prop = get_property(np, "linux,bootx-height", NULL); + prop = of_get_property(np, "linux,bootx-height", NULL); if (prop == NULL) - prop = get_property(np, "height", NULL); + prop = of_get_property(np, "height", NULL); if (prop == NULL) return -EINVAL; height = *prop; - prop = get_property(np, "linux,bootx-depth", NULL); + prop = of_get_property(np, "linux,bootx-depth", NULL); if (prop == NULL) - prop = get_property(np, "depth", NULL); + prop = of_get_property(np, "depth", NULL); if (prop == NULL) return -EINVAL; depth = *prop; pitch = width * ((depth + 7) / 8); - prop = get_property(np, "linux,bootx-linebytes", NULL); + prop = of_get_property(np, "linux,bootx-linebytes", NULL); if (prop == NULL) - prop = get_property(np, "linebytes", NULL); + prop = of_get_property(np, "linebytes", NULL); if (prop && *prop != 0xffffffffu) pitch = *prop; if (pitch == 1) pitch = 0x1000; - prop = get_property(np, "address", NULL); + prop = of_get_property(np, "address", NULL); if (prop) address = *prop; @@ -219,7 +219,7 @@ int __init btext_find_display(int allow_nonstdout) struct device_node *np = NULL; int rc = -ENODEV; - name = get_property(of_chosen, "linux,stdout-path", NULL); + name = of_get_property(of_chosen, "linux,stdout-path", NULL); if (name != NULL) { np = of_find_node_by_path(name); if (np != NULL) { @@ -236,7 +236,7 @@ int __init btext_find_display(int allow_nonstdout) return rc; for (np = NULL; (np = of_find_node_by_type(np, "display"));) { - if (get_property(np, "linux,opened", NULL)) { + if (of_get_property(np, "linux,opened", NULL)) { printk("trying %s ...\n", np->full_name); rc = btext_initialize(np); printk("result: %d\n", rc); diff --git a/arch/powerpc/kernel/cpu_setup_pa6t.S b/arch/powerpc/kernel/cpu_setup_pa6t.S index 4047be2..d62cb9c 100644 --- a/arch/powerpc/kernel/cpu_setup_pa6t.S +++ b/arch/powerpc/kernel/cpu_setup_pa6t.S @@ -34,7 +34,7 @@ _GLOBAL(__setup_cpu_pa6t) beqlr mfspr r0,SPRN_HID5 - ori r0,r0,0x30 + ori r0,r0,0x38 mtspr SPRN_HID5,r0 mfspr r0,SPRN_LPCR diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index e4006dc..9cb24d2 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -389,6 +389,8 @@ static struct cpu_spec cpu_specs[] = { .pmc_type = PPC_PMC_PA6T, .cpu_setup = __setup_cpu_pa6t, .cpu_restore = __restore_cpu_pa6t, + .oprofile_cpu_type = "ppc64/pa6t", + .oprofile_type = PPC_OPROFILE_PA6T, .platform = "pa6t", }, { /* default match */ @@ -558,6 +560,18 @@ static struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_750cx, .platform = "ppc750", }, + { /* 750CL */ + .pvr_mask = 0xfffff0f0, + .pvr_value = 0x00087010, + .cpu_name = "750CL", + .cpu_features = CPU_FTRS_750CL, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 4, + .cpu_setup = __setup_cpu_750, + .platform = "ppc750", + }, { /* 745/755 */ .pvr_mask = 0xfffff000, .pvr_value = 0x00083000, diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index c03e829..c29d165 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -191,7 +191,6 @@ stack_ovf: 0: _GLOBAL(DoSyscall) - stw r0,THREAD+LAST_SYSCALL(r2) stw r3,ORIG_GPR3(r1) li r12,0 stw r12,RESULT(r1) diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 97cedcd6..1111fce 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -278,8 +278,12 @@ exception_marker: beq- 1f; \ ld r1,PACAKSAVE(r13); /* kernel stack to use */ \ 1: cmpdi cr1,r1,0; /* check if r1 is in userspace */ \ - bge- cr1,bad_stack; /* abort if it is */ \ - std r9,_CCR(r1); /* save CR in stackframe */ \ + bge- cr1,2f; /* abort if it is */ \ + b 3f; \ +2: li r1,(n); /* will be reloaded later */ \ + sth r1,PACA_TRAP_SAVE(r13); \ + b bad_stack; \ +3: std r9,_CCR(r1); /* save CR in stackframe */ \ std r11,_NIP(r1); /* save SRR0 in stackframe */ \ std r12,_MSR(r1); /* save SRR1 in stackframe */ \ std r10,0(r1); /* make stack chain pointer */ \ @@ -940,6 +944,8 @@ bad_stack: SAVE_2GPRS(7,r1) SAVE_10GPRS(12,r1) SAVE_10GPRS(22,r1) + lhz r12,PACA_TRAP_SAVE(r13) + std r12,_TRAP(r1) addi r11,r1,INT_FRAME_SIZE std r11,0(r1) li r12,0 @@ -1555,7 +1561,6 @@ _GLOBAL(generic_secondary_smp_init) /* turn on 64-bit mode */ bl .enable_64b_mode - isync /* Set up a paca value for this processor. Since we have the * physical cpu id in r24, we need to search the pacas to find @@ -1735,10 +1740,6 @@ _STATIC(__boot_from_prom) /* We never return */ trap -/* - * At this point, r3 contains the physical address we are running at, - * returned by prom_init() - */ _STATIC(__after_prom_start) /* @@ -1851,7 +1852,6 @@ __secondary_start_pmac_0: _GLOBAL(pmac_secondary_start) /* turn on 64-bit mode */ bl .enable_64b_mode - isync /* Copy some CPU settings from CPU 0 */ bl .__restore_cpu_ppc970 diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c index 82bd2f1..9a8c9af 100644 --- a/arch/powerpc/kernel/ibmebus.c +++ b/arch/powerpc/kernel/ibmebus.c @@ -2,36 +2,37 @@ * IBM PowerPC IBM eBus Infrastructure Support. * * Copyright (c) 2005 IBM Corporation + * Joachim Fenkes <fenkes@de.ibm.com> * Heiko J Schick <schickhj@de.ibm.com> - * + * * All rights reserved. * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. + * This source code is distributed under a dual license of GPL v2.0 and OpenIB + * BSD. * * OpenIB BSD License * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation * and/or other materials - * provided with the distribution. + * provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ @@ -43,19 +44,19 @@ #include <asm/ibmebus.h> #include <asm/abs_addr.h> -static struct ibmebus_dev ibmebus_bus_device = { /* fake "parent" device */ - .name = ibmebus_bus_device.ofdev.dev.bus_id, - .ofdev.dev.bus_id = "ibmebus", - .ofdev.dev.bus = &ibmebus_bus_type, +static struct device ibmebus_bus_device = { /* fake "parent" device */ + .bus_id = "ibmebus", }; +struct bus_type ibmebus_bus_type; + static void *ibmebus_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag) { void *mem; - + mem = kmalloc(size, flag); *dma_handle = (dma_addr_t)mem; @@ -63,7 +64,7 @@ static void *ibmebus_alloc_coherent(struct device *dev, } static void ibmebus_free_coherent(struct device *dev, - size_t size, void *vaddr, + size_t size, void *vaddr, dma_addr_t dma_handle) { kfree(vaddr); @@ -79,7 +80,7 @@ static dma_addr_t ibmebus_map_single(struct device *dev, static void ibmebus_unmap_single(struct device *dev, dma_addr_t dma_addr, - size_t size, + size_t size, enum dma_data_direction direction) { return; @@ -90,13 +91,13 @@ static int ibmebus_map_sg(struct device *dev, int nents, enum dma_data_direction direction) { int i; - + for (i = 0; i < nents; i++) { - sg[i].dma_address = (dma_addr_t)page_address(sg[i].page) + sg[i].dma_address = (dma_addr_t)page_address(sg[i].page) + sg[i].offset; sg[i].dma_length = sg[i].length; } - + return nents; } @@ -128,15 +129,15 @@ static int ibmebus_bus_probe(struct device *dev) struct ibmebus_driver *ibmebusdrv = to_ibmebus_driver(dev->driver); const struct of_device_id *id; int error = -ENODEV; - + if (!ibmebusdrv->probe) return error; - + id = of_match_device(ibmebusdrv->id_table, &ibmebusdev->ofdev); if (id) { error = ibmebusdrv->probe(ibmebusdev, id); } - + return error; } @@ -144,11 +145,11 @@ static int ibmebus_bus_remove(struct device *dev) { struct ibmebus_dev *ibmebusdev = to_ibmebus_dev(dev); struct ibmebus_driver *ibmebusdrv = to_ibmebus_driver(dev->driver); - + if (ibmebusdrv->remove) { return ibmebusdrv->remove(ibmebusdev); } - + return 0; } @@ -158,21 +159,12 @@ static void __devinit ibmebus_dev_release(struct device *dev) kfree(to_ibmebus_dev(dev)); } -static ssize_t ibmebusdev_show_name(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%s\n", to_ibmebus_dev(dev)->name); -} -static DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, ibmebusdev_show_name, - NULL); - -static struct ibmebus_dev* __devinit ibmebus_register_device_common( +static int __devinit ibmebus_register_device_common( struct ibmebus_dev *dev, const char *name) { int err = 0; - dev->name = name; - dev->ofdev.dev.parent = &ibmebus_bus_device.ofdev.dev; + dev->ofdev.dev.parent = &ibmebus_bus_device; dev->ofdev.dev.bus = &ibmebus_bus_type; dev->ofdev.dev.release = ibmebus_dev_release; @@ -181,17 +173,15 @@ static struct ibmebus_dev* __devinit ibmebus_register_device_common( dev->ofdev.dev.archdata.numa_node = of_node_to_nid(dev->ofdev.node); /* An ibmebusdev is based on a of_device. We have to change the - * bus type to use our own DMA mapping operations. - */ + * bus type to use our own DMA mapping operations. + */ if ((err = of_device_register(&dev->ofdev)) != 0) { printk(KERN_ERR "%s: failed to register device (%d).\n", __FUNCTION__, err); - return NULL; + return -ENODEV; } - - device_create_file(&dev->ofdev.dev, &dev_attr_name); - - return dev; + + return 0; } static struct ibmebus_dev* __devinit ibmebus_register_device_node( @@ -201,35 +191,35 @@ static struct ibmebus_dev* __devinit ibmebus_register_device_node( const char *loc_code; int length; - loc_code = get_property(dn, "ibm,loc-code", NULL); + loc_code = of_get_property(dn, "ibm,loc-code", NULL); if (!loc_code) { printk(KERN_WARNING "%s: node %s missing 'ibm,loc-code'\n", __FUNCTION__, dn->name ? dn->name : "<unknown>"); - return NULL; + return ERR_PTR(-EINVAL); } - + if (strlen(loc_code) == 0) { printk(KERN_WARNING "%s: 'ibm,loc-code' is invalid\n", __FUNCTION__); - return NULL; + return ERR_PTR(-EINVAL); } dev = kzalloc(sizeof(struct ibmebus_dev), GFP_KERNEL); if (!dev) { - return NULL; + return ERR_PTR(-ENOMEM); } dev->ofdev.node = of_node_get(dn); - + length = strlen(loc_code); - memcpy(dev->ofdev.dev.bus_id, loc_code - + (length - min(length, BUS_ID_SIZE - 1)), + memcpy(dev->ofdev.dev.bus_id, loc_code + + (length - min(length, BUS_ID_SIZE - 1)), min(length, BUS_ID_SIZE - 1)); /* Register with generic device framework. */ - if (ibmebus_register_device_common(dev, dn->name) == NULL) { + if (ibmebus_register_device_common(dev, dn->name) != 0) { kfree(dev); - return NULL; + return ERR_PTR(-ENODEV); } return dev; @@ -238,17 +228,16 @@ static struct ibmebus_dev* __devinit ibmebus_register_device_node( static void ibmebus_probe_of_nodes(char* name) { struct device_node *dn = NULL; - + while ((dn = of_find_node_by_name(dn, name))) { - if (ibmebus_register_device_node(dn) == NULL) { + if (IS_ERR(ibmebus_register_device_node(dn))) { of_node_put(dn); - return; } } - + of_node_put(dn); - + return; } @@ -262,17 +251,21 @@ static void ibmebus_add_devices_by_id(struct of_device_id *idt) return; } -static int ibmebus_match_helper(struct device *dev, void *data) +static int ibmebus_match_name(struct device *dev, void *data) { - if (strcmp((char*)data, to_ibmebus_dev(dev)->name) == 0) + const struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev); + const char *name; + + name = of_get_property(ebus_dev->ofdev.node, "name", NULL); + + if (name && (strcmp(data, name) == 0)) return 1; - + return 0; } static int ibmebus_unregister_device(struct device *dev) { - device_remove_file(dev, &dev_attr_name); of_device_unregister(to_of_device(dev)); return 0; @@ -281,17 +274,16 @@ static int ibmebus_unregister_device(struct device *dev) static void ibmebus_remove_devices_by_id(struct of_device_id *idt) { struct device *dev; - + while (strlen(idt->name) > 0) { - while ((dev = bus_find_device(&ibmebus_bus_type, NULL, + while ((dev = bus_find_device(&ibmebus_bus_type, NULL, (void*)idt->name, - ibmebus_match_helper))) { + ibmebus_match_name))) { ibmebus_unregister_device(dev); } idt++; - } - + return; } @@ -307,30 +299,33 @@ int ibmebus_register_driver(struct ibmebus_driver *drv) if ((err = driver_register(&drv->driver) != 0)) return err; + /* remove all supported devices first, in case someone + * probed them manually before registering the driver */ + ibmebus_remove_devices_by_id(drv->id_table); ibmebus_add_devices_by_id(drv->id_table); - + return 0; } EXPORT_SYMBOL(ibmebus_register_driver); void ibmebus_unregister_driver(struct ibmebus_driver *drv) -{ +{ driver_unregister(&drv->driver); ibmebus_remove_devices_by_id(drv->id_table); } EXPORT_SYMBOL(ibmebus_unregister_driver); int ibmebus_request_irq(struct ibmebus_dev *dev, - u32 ist, + u32 ist, irq_handler_t handler, unsigned long irq_flags, const char * devname, void *dev_id) { unsigned int irq = irq_create_mapping(NULL, ist); - + if (irq == NO_IRQ) return -EINVAL; - + return request_irq(irq, handler, irq_flags, devname, dev_id); } @@ -339,56 +334,163 @@ EXPORT_SYMBOL(ibmebus_request_irq); void ibmebus_free_irq(struct ibmebus_dev *dev, u32 ist, void *dev_id) { unsigned int irq = irq_find_mapping(NULL, ist); - + free_irq(irq, dev_id); } EXPORT_SYMBOL(ibmebus_free_irq); static int ibmebus_bus_match(struct device *dev, struct device_driver *drv) -{ +{ const struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev); struct ibmebus_driver *ebus_drv = to_ibmebus_driver(drv); const struct of_device_id *ids = ebus_drv->id_table; const struct of_device_id *found_id; - + if (!ids) return 0; - + found_id = of_match_device(ids, &ebus_dev->ofdev); if (found_id) return 1; - + return 0; } +static ssize_t name_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev); + const char *name = of_get_property(ebus_dev->ofdev.node, "name", NULL); + return sprintf(buf, "%s\n", name); +} + +static struct device_attribute ibmebus_dev_attrs[] = { + __ATTR_RO(name), + __ATTR_NULL +}; + +static int ibmebus_match_path(struct device *dev, void *data) +{ + int rc; + struct device_node *dn = + of_node_get(to_ibmebus_dev(dev)->ofdev.node); + + rc = (dn->full_name && (strcasecmp((char*)data, dn->full_name) == 0)); + + of_node_put(dn); + return rc; +} + +static char *ibmebus_chomp(const char *in, size_t count) +{ + char *out = (char*)kmalloc(count + 1, GFP_KERNEL); + if (!out) + return NULL; + + memcpy(out, in, count); + out[count] = '\0'; + if (out[count - 1] == '\n') + out[count - 1] = '\0'; + + return out; +} + +static ssize_t ibmebus_store_probe(struct bus_type *bus, + const char *buf, size_t count) +{ + struct device_node *dn = NULL; + struct ibmebus_dev *dev; + char *path; + ssize_t rc; + + path = ibmebus_chomp(buf, count); + if (!path) + return -ENOMEM; + + if (bus_find_device(&ibmebus_bus_type, NULL, path, + ibmebus_match_path)) { + printk(KERN_WARNING "%s: %s has already been probed\n", + __FUNCTION__, path); + rc = -EINVAL; + goto out; + } + + if ((dn = of_find_node_by_path(path))) { + dev = ibmebus_register_device_node(dn); + of_node_put(dn); + rc = IS_ERR(dev) ? PTR_ERR(dev) : count; + } else { + printk(KERN_WARNING "%s: no such device node: %s\n", + __FUNCTION__, path); + rc = -ENODEV; + } + +out: + kfree(path); + return rc; +} + +static ssize_t ibmebus_store_remove(struct bus_type *bus, + const char *buf, size_t count) +{ + struct device *dev; + char *path; + + path = ibmebus_chomp(buf, count); + if (!path) + return -ENOMEM; + + if ((dev = bus_find_device(&ibmebus_bus_type, NULL, path, + ibmebus_match_path))) { + ibmebus_unregister_device(dev); + + kfree(path); + return count; + } else { + printk(KERN_WARNING "%s: %s not on the bus\n", + __FUNCTION__, path); + + kfree(path); + return -ENODEV; + } +} + +static struct bus_attribute ibmebus_bus_attrs[] = { + __ATTR(probe, S_IWUSR, NULL, ibmebus_store_probe), + __ATTR(remove, S_IWUSR, NULL, ibmebus_store_remove), + __ATTR_NULL +}; + struct bus_type ibmebus_bus_type = { - .name = "ibmebus", - .match = ibmebus_bus_match, + .name = "ibmebus", + .match = ibmebus_bus_match, + .dev_attrs = ibmebus_dev_attrs, + .bus_attrs = ibmebus_bus_attrs }; EXPORT_SYMBOL(ibmebus_bus_type); static int __init ibmebus_bus_init(void) { int err; - + printk(KERN_INFO "IBM eBus Device Driver\n"); - + err = bus_register(&ibmebus_bus_type); if (err) { printk(KERN_ERR ":%s: failed to register IBM eBus.\n", __FUNCTION__); return err; } - - err = device_register(&ibmebus_bus_device.ofdev.dev); + + err = device_register(&ibmebus_bus_device); if (err) { - printk(KERN_WARNING "%s: device_register returned %i\n", + printk(KERN_WARNING "%s: device_register returned %i\n", __FUNCTION__, err); bus_unregister(&ibmebus_bus_type); return err; } - + return 0; } __initcall(ibmebus_bus_init); diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 95edad4..c08ceca 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -47,6 +47,8 @@ static int novmerge = 0; static int novmerge = 1; #endif +static int protect4gb = 1; + static inline unsigned long iommu_num_pages(unsigned long vaddr, unsigned long slen) { @@ -58,6 +60,16 @@ static inline unsigned long iommu_num_pages(unsigned long vaddr, return npages; } +static int __init setup_protect4gb(char *str) +{ + if (strcmp(str, "on") == 0) + protect4gb = 1; + else if (strcmp(str, "off") == 0) + protect4gb = 0; + + return 1; +} + static int __init setup_iommu(char *str) { if (!strcmp(str, "novmerge")) @@ -67,6 +79,7 @@ static int __init setup_iommu(char *str) return 1; } +__setup("protect4gb=", setup_protect4gb); __setup("iommu=", setup_iommu); static unsigned long iommu_range_alloc(struct iommu_table *tbl, @@ -429,6 +442,9 @@ void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist, struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid) { unsigned long sz; + unsigned long start_index, end_index; + unsigned long entries_per_4g; + unsigned long index; static int welcomed = 0; struct page *page; @@ -450,7 +466,7 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid) #ifdef CONFIG_CRASH_DUMP if (ppc_md.tce_get) { - unsigned long index, tceval; + unsigned long tceval; unsigned long tcecount = 0; /* @@ -480,6 +496,23 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid) ppc_md.tce_free(tbl, tbl->it_offset, tbl->it_size); #endif + /* + * DMA cannot cross 4 GB boundary. Mark last entry of each 4 + * GB chunk as reserved. + */ + if (protect4gb) { + entries_per_4g = 0x100000000l >> IOMMU_PAGE_SHIFT; + + /* Mark the last bit before a 4GB boundary as used */ + start_index = tbl->it_offset | (entries_per_4g - 1); + start_index -= tbl->it_offset; + + end_index = tbl->it_size; + + for (index = start_index; index < end_index - 1; index += entries_per_4g) + __set_bit(index, tbl->it_map); + } + if (!welcomed) { printk(KERN_INFO "IOMMU table initialized, virtual merging %s\n", novmerge ? "disabled" : "enabled"); diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 1009308..6c83fe2 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -394,7 +394,7 @@ EXPORT_SYMBOL(do_softirq); #ifdef CONFIG_PPC_MERGE static LIST_HEAD(irq_hosts); -static spinlock_t irq_big_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(irq_big_lock); static DEFINE_PER_CPU(unsigned int, irq_radix_reader); static unsigned int irq_radix_writer; struct irq_map_entry irq_map[NR_IRQS]; diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index dd2886f..ef647e7 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c @@ -59,12 +59,14 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) } if (!ret) { - memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); + memcpy(p->ainsn.insn, p->addr, + MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); p->opcode = *p->addr; flush_icache_range((unsigned long)p->ainsn.insn, (unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t)); } + p->ainsn.boostable = 0; return ret; } @@ -232,6 +234,38 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) return 1; ss_probe: + if (p->ainsn.boostable >= 0) { + unsigned int insn = *p->ainsn.insn; + + /* regs->nip is also adjusted if emulate_step returns 1 */ + ret = emulate_step(regs, insn); + if (ret > 0) { + /* + * Once this instruction has been boosted + * successfully, set the boostable flag + */ + if (unlikely(p->ainsn.boostable == 0)) + p->ainsn.boostable = 1; + + if (p->post_handler) + p->post_handler(p, regs, 0); + + kcb->kprobe_status = KPROBE_HIT_SSDONE; + reset_current_kprobe(); + preempt_enable_no_resched(); + return 1; + } else if (ret < 0) { + /* + * We don't allow kprobes on mtmsr(d)/rfi(d), etc. + * So, we should never get here... but, its still + * good to catch them, just in case... + */ + printk("Can't step on instruction %x\n", insn); + BUG(); + } else if (ret == 0) + /* This instruction can't be boosted */ + p->ainsn.boostable = -1; + } prepare_singlestep(p, regs); kcb->kprobe_status = KPROBE_HIT_SS; return 1; diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c index 325f490..63dd2c3 100644 --- a/arch/powerpc/kernel/legacy_serial.c +++ b/arch/powerpc/kernel/legacy_serial.c @@ -44,12 +44,12 @@ static int __init add_legacy_port(struct device_node *np, int want_index, int index; /* get clock freq. if present */ - clk = get_property(np, "clock-frequency", NULL); + clk = of_get_property(np, "clock-frequency", NULL); if (clk && *clk) clock = *clk; /* get default speed if present */ - spd = get_property(np, "current-speed", NULL); + spd = of_get_property(np, "current-speed", NULL); /* If we have a location index, then try to use it */ if (want_index >= 0 && want_index < MAX_LEGACY_SERIAL_PORTS) @@ -121,11 +121,11 @@ static int __init add_legacy_soc_port(struct device_node *np, /* We only support ports that have a clock frequency properly * encoded in the device-tree. */ - if (get_property(np, "clock-frequency", NULL) == NULL) + if (of_get_property(np, "clock-frequency", NULL) == NULL) return -1; /* if rtas uses this device, don't try to use it as well */ - if (get_property(np, "used-by-rtas", NULL) != NULL) + if (of_get_property(np, "used-by-rtas", NULL) != NULL) return -1; /* Get the address */ @@ -157,7 +157,7 @@ static int __init add_legacy_isa_port(struct device_node *np, DBG(" -> add_legacy_isa_port(%s)\n", np->full_name); /* Get the ISA port number */ - reg = get_property(np, "reg", NULL); + reg = of_get_property(np, "reg", NULL); if (reg == NULL) return -1; @@ -168,7 +168,7 @@ static int __init add_legacy_isa_port(struct device_node *np, /* Now look for an "ibm,aix-loc" property that gives us ordering * if any... */ - typep = get_property(np, "ibm,aix-loc", NULL); + typep = of_get_property(np, "ibm,aix-loc", NULL); /* If we have a location index, then use it */ if (typep && *typep == 'S') @@ -206,7 +206,7 @@ static int __init add_legacy_pci_port(struct device_node *np, * compatible UARTs on PCI need all sort of quirks (port offsets * etc...) that this code doesn't know about */ - if (get_property(np, "clock-frequency", NULL) == NULL) + if (of_get_property(np, "clock-frequency", NULL) == NULL) return -1; /* Get the PCI address. Assume BAR 0 */ @@ -232,7 +232,7 @@ static int __init add_legacy_pci_port(struct device_node *np, * we get to their "reg" property */ if (np != pci_dev) { - const u32 *reg = get_property(np, "reg", NULL); + const u32 *reg = of_get_property(np, "reg", NULL); if (reg && (*reg < 4)) index = lindex = *reg; } @@ -296,7 +296,7 @@ void __init find_legacy_serial_ports(void) DBG(" -> find_legacy_serial_port()\n"); /* Now find out if one of these is out firmware console */ - path = get_property(of_chosen, "linux,stdout-path", NULL); + path = of_get_property(of_chosen, "linux,stdout-path", NULL); if (path != NULL) { stdout = of_find_node_by_path(path); if (stdout) @@ -529,7 +529,7 @@ static int __init check_legacy_serial_console(void) } /* We are getting a weird phandle from OF ... */ /* ... So use the full path instead */ - name = get_property(of_chosen, "linux,stdout-path", NULL); + name = of_get_property(of_chosen, "linux,stdout-path", NULL); if (name == NULL) { DBG(" no linux,stdout-path !\n"); return -ENODEV; @@ -541,12 +541,12 @@ static int __init check_legacy_serial_console(void) } DBG("stdout is %s\n", prom_stdout->full_name); - name = get_property(prom_stdout, "name", NULL); + name = of_get_property(prom_stdout, "name", NULL); if (!name) { DBG(" stdout package has no name !\n"); goto not_found; } - spd = get_property(prom_stdout, "current-speed", NULL); + spd = of_get_property(prom_stdout, "current-speed", NULL); if (spd) speed = *spd; diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index 89486b6..c492cee 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c @@ -130,30 +130,31 @@ static int iseries_lparcfg_data(struct seq_file *m, void *v) /* * Methods used to fetch LPAR data when running on a pSeries platform. */ -/* find a better place for this function... */ static void log_plpar_hcall_return(unsigned long rc, char *tag) { - if (rc == 0) /* success, return */ + switch(rc) { + case 0: return; -/* check for null tag ? */ - if (rc == H_HARDWARE) - printk(KERN_INFO - "plpar-hcall (%s) failed with hardware fault\n", tag); - else if (rc == H_FUNCTION) - printk(KERN_INFO - "plpar-hcall (%s) failed; function not allowed\n", tag); - else if (rc == H_AUTHORITY) - printk(KERN_INFO - "plpar-hcall (%s) failed; not authorized to this" - " function\n", tag); - else if (rc == H_PARAMETER) - printk(KERN_INFO "plpar-hcall (%s) failed; Bad parameter(s)\n", - tag); - else - printk(KERN_INFO - "plpar-hcall (%s) failed with unexpected rc(0x%lx)\n", - tag, rc); - + case H_HARDWARE: + printk(KERN_INFO "plpar-hcall (%s) " + "Hardware fault\n", tag); + return; + case H_FUNCTION: + printk(KERN_INFO "plpar-hcall (%s) " + "Function not allowed\n", tag); + return; + case H_AUTHORITY: + printk(KERN_INFO "plpar-hcall (%s) " + "Not authorized to this function\n", tag); + return; + case H_PARAMETER: + printk(KERN_INFO "plpar-hcall (%s) " + "Bad parameter(s)\n",tag); + return; + default: + printk(KERN_INFO "plpar-hcall (%s) " + "Unexpected rc(0x%lx)\n", tag, rc); + } } /* @@ -321,15 +322,16 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v) struct device_node *rtas_node; const int *lrdrp = NULL; - rtas_node = find_path_device("/rtas"); + rtas_node = of_find_node_by_path("/rtas"); if (rtas_node) - lrdrp = get_property(rtas_node, "ibm,lrdr-capacity", NULL); + lrdrp = of_get_property(rtas_node, "ibm,lrdr-capacity", NULL); if (lrdrp == NULL) { partition_potential_processors = vdso_data->processorCount; } else { partition_potential_processors = *(lrdrp + 4); } + of_node_put(rtas_node); partition_active_processors = lparcfg_count_active_processors(); @@ -537,25 +539,27 @@ static int lparcfg_data(struct seq_file *m, void *v) seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS); - rootdn = find_path_device("/"); + rootdn = of_find_node_by_path("/"); if (rootdn) { - tmp = get_property(rootdn, "model", NULL); + tmp = of_get_property(rootdn, "model", NULL); if (tmp) { model = tmp; /* Skip "IBM," - see platforms/iseries/dt.c */ if (firmware_has_feature(FW_FEATURE_ISERIES)) model += 4; } - tmp = get_property(rootdn, "system-id", NULL); + tmp = of_get_property(rootdn, "system-id", NULL); if (tmp) { system_id = tmp; /* Skip "IBM," - see platforms/iseries/dt.c */ if (firmware_has_feature(FW_FEATURE_ISERIES)) system_id += 4; } - lp_index_ptr = get_property(rootdn, "ibm,partition-no", NULL); + lp_index_ptr = of_get_property(rootdn, "ibm,partition-no", + NULL); if (lp_index_ptr) lp_index = *lp_index_ptr; + of_node_put(rootdn); } seq_printf(m, "serial_number=%s\n", system_id); seq_printf(m, "system_type=%s\n", model); diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index a24b09c..704375b 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c @@ -72,8 +72,8 @@ int default_machine_kexec_prepare(struct kimage *image) /* We also should not overwrite the tce tables */ for (node = of_find_node_by_type(NULL, "pci"); node != NULL; node = of_find_node_by_type(node, "pci")) { - basep = get_property(node, "linux,tce-base", NULL); - sizep = get_property(node, "linux,tce-size", NULL); + basep = of_get_property(node, "linux,tce-base", NULL); + sizep = of_get_property(node, "linux,tce-size", NULL); if (basep == NULL || sizep == NULL) continue; @@ -294,19 +294,19 @@ static unsigned long htab_base, kernel_end; static struct property htab_base_prop = { .name = "linux,htab-base", .length = sizeof(unsigned long), - .value = (unsigned char *)&htab_base, + .value = &htab_base, }; static struct property htab_size_prop = { .name = "linux,htab-size", .length = sizeof(unsigned long), - .value = (unsigned char *)&htab_size_bytes, + .value = &htab_size_bytes, }; static struct property kernel_end_prop = { .name = "linux,kernel-end", .length = sizeof(unsigned long), - .value = (unsigned char *)&kernel_end, + .value = &kernel_end, }; static void __init export_htab_values(void) @@ -335,7 +335,7 @@ static void __init export_htab_values(void) static struct property crashk_base_prop = { .name = "linux,crashkernel-base", .length = sizeof(unsigned long), - .value = (unsigned char *)&crashk_res.start, + .value = &crashk_res.start, }; static unsigned long crashk_size; @@ -343,7 +343,7 @@ static unsigned long crashk_size; static struct property crashk_size_prop = { .name = "linux,crashkernel-size", .length = sizeof(unsigned long), - .value = (unsigned char *)&crashk_size, + .value = &crashk_size, }; static void __init export_crashk_values(void) diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 412bea3..98decf8 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S @@ -734,10 +734,6 @@ _GLOBAL(abs) sub r3,r3,r4 blr -_GLOBAL(_get_SP) - mr r3,r1 /* Close enough */ - blr - /* * Create a kernel thread * kernel_thread(fn, arg, flags) diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c index e921514..0c8ea76 100644 --- a/arch/powerpc/kernel/of_device.c +++ b/arch/powerpc/kernel/of_device.c @@ -120,6 +120,117 @@ void of_device_unregister(struct of_device *ofdev) } +static ssize_t of_device_get_modalias(struct of_device *ofdev, + char *str, ssize_t len) +{ + const char *compat; + int cplen, i; + ssize_t tsize, csize, repend; + + /* Name & Type */ + csize = snprintf(str, len, "of:N%sT%s", + ofdev->node->name, ofdev->node->type); + + /* Get compatible property if any */ + compat = of_get_property(ofdev->node, "compatible", &cplen); + if (!compat) + return csize; + + /* Find true end (we tolerate multiple \0 at the end */ + for (i=(cplen-1); i>=0 && !compat[i]; i--) + cplen--; + if (!cplen) + return csize; + cplen++; + + /* Check space (need cplen+1 chars including final \0) */ + tsize = csize + cplen; + repend = tsize; + + if (csize>=len) /* @ the limit, all is already filled */ + return tsize; + + if (tsize>=len) { /* limit compat list */ + cplen = len-csize-1; + repend = len; + } + + /* Copy and do char replacement */ + memcpy(&str[csize+1], compat, cplen); + for (i=csize; i<repend; i++) { + char c = str[i]; + if (c=='\0') + str[i] = 'C'; + else if (c==' ') + str[i] = '_'; + } + + return tsize; +} + +int of_device_uevent(struct device *dev, + char **envp, int num_envp, char *buffer, int buffer_size) +{ + struct of_device *ofdev; + const char *compat; + int i = 0, length = 0, seen = 0, cplen, sl; + + if (!dev) + return -ENODEV; + + ofdev = to_of_device(dev); + + if (add_uevent_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "OF_NAME=%s", ofdev->node->name)) + return -ENOMEM; + + if (add_uevent_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "OF_TYPE=%s", ofdev->node->type)) + return -ENOMEM; + + /* Since the compatible field can contain pretty much anything + * it's not really legal to split it out with commas. We split it + * up using a number of environment variables instead. */ + + compat = of_get_property(ofdev->node, "compatible", &cplen); + while (compat && *compat && cplen > 0) { + if (add_uevent_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "OF_COMPATIBLE_%d=%s", seen, compat)) + return -ENOMEM; + + sl = strlen (compat) + 1; + compat += sl; + cplen -= sl; + seen++; + } + + if (add_uevent_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "OF_COMPATIBLE_N=%d", seen)) + return -ENOMEM; + + /* modalias is trickier, we add it in 2 steps */ + if (add_uevent_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "MODALIAS=")) + return -ENOMEM; + + sl = of_device_get_modalias(ofdev, &buffer[length-1], + buffer_size-length); + if (sl >= (buffer_size-length)) + return -ENOMEM; + + length += sl; + + envp[i] = NULL; + + return 0; +} + + EXPORT_SYMBOL(of_match_node); EXPORT_SYMBOL(of_match_device); EXPORT_SYMBOL(of_device_register); @@ -127,3 +238,4 @@ EXPORT_SYMBOL(of_device_unregister); EXPORT_SYMBOL(of_dev_get); EXPORT_SYMBOL(of_dev_put); EXPORT_SYMBOL(of_release_dev); +EXPORT_SYMBOL(of_device_uevent); diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c index 9e7a4d2..908ed79 100644 --- a/arch/powerpc/kernel/of_platform.c +++ b/arch/powerpc/kernel/of_platform.c @@ -133,6 +133,7 @@ static int of_platform_device_resume(struct device * dev) struct bus_type of_platform_bus_type = { .name = "of_platform", .match = of_platform_bus_match, + .uevent = of_device_uevent, .probe = of_platform_device_probe, .remove = of_platform_device_remove, .suspend = of_platform_device_suspend, @@ -177,7 +178,7 @@ static void of_platform_make_bus_id(struct of_device *dev) * and 'D' for MMIO DCRs. */ #ifdef CONFIG_PPC_DCR - reg = get_property(node, "dcr-reg", NULL); + reg = of_get_property(node, "dcr-reg", NULL); if (reg) { #ifdef CONFIG_PPC_DCR_NATIVE snprintf(name, BUS_ID_SIZE, "d%x.%s", @@ -197,7 +198,7 @@ static void of_platform_make_bus_id(struct of_device *dev) /* * For MMIO, get the physical address */ - reg = get_property(node, "reg", NULL); + reg = of_get_property(node, "reg", NULL); if (reg) { addr = of_translate_address(node, reg); if (addr != OF_BAD_ADDR) { diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index d8ef2e1..f022862 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c @@ -637,7 +637,7 @@ make_one_node_map(struct device_node* node, u8 pci_bus) if (pci_bus >= pci_bus_count) return; - bus_range = get_property(node, "bus-range", &len); + bus_range = of_get_property(node, "bus-range", &len); if (bus_range == NULL || len < 2 * sizeof(int)) { printk(KERN_WARNING "Can't get bus-range for %s, " "assuming it starts at 0\n", node->full_name); @@ -649,17 +649,20 @@ make_one_node_map(struct device_node* node, u8 pci_bus) struct pci_dev* dev; const unsigned int *class_code, *reg; - class_code = get_property(node, "class-code", NULL); + class_code = of_get_property(node, "class-code", NULL); if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI && (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) continue; - reg = get_property(node, "reg", NULL); + reg = of_get_property(node, "reg", NULL); if (!reg) continue; - dev = pci_find_slot(pci_bus, ((reg[0] >> 8) & 0xff)); - if (!dev || !dev->subordinate) + dev = pci_get_bus_and_slot(pci_bus, ((reg[0] >> 8) & 0xff)); + if (!dev || !dev->subordinate) { + pci_dev_put(dev); continue; + } make_one_node_map(node, dev->subordinate->number); + pci_dev_put(dev); } } @@ -669,6 +672,7 @@ pcibios_make_OF_bus_map(void) int i; struct pci_controller* hose; struct property *map_prop; + struct device_node *dn; pci_to_OF_bus_map = kmalloc(pci_bus_count, GFP_KERNEL); if (!pci_to_OF_bus_map) { @@ -690,12 +694,13 @@ pcibios_make_OF_bus_map(void) continue; make_one_node_map(node, hose->first_busno); } - map_prop = of_find_property(find_path_device("/"), - "pci-OF-bus-map", NULL); + dn = of_find_node_by_path("/"); + map_prop = of_find_property(dn, "pci-OF-bus-map", NULL); if (map_prop) { BUG_ON(pci_bus_count > map_prop->length); memcpy(map_prop->value, pci_to_OF_bus_map, pci_bus_count); } + of_node_put(dn); #ifdef DEBUG printk("PCI->OF bus map:\n"); for (i=0; i<pci_bus_count; i++) { @@ -724,7 +729,7 @@ scan_OF_pci_childs(struct device_node* node, pci_OF_scan_iterator filter, void* * a fake root for all functions of a multi-function device, * we go down them as well. */ - class_code = get_property(node, "class-code", NULL); + class_code = of_get_property(node, "class-code", NULL); if ((!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI && (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) && strcmp(node->name, "multifunc-device")) @@ -744,7 +749,7 @@ static struct device_node *scan_OF_for_pci_dev(struct device_node *parent, unsigned int psize; while ((np = of_get_next_child(parent, np)) != NULL) { - reg = get_property(np, "reg", &psize); + reg = of_get_property(np, "reg", &psize); if (reg == NULL || psize < 4) continue; if (((reg[0] >> 8) & 0xff) == devfn) @@ -859,7 +864,7 @@ pci_device_from_OF_node(struct device_node* node, u8* bus, u8* devfn) if (!scan_OF_pci_childs(((struct device_node*)hose->arch_data)->child, find_OF_pci_device_filter, (void *)node)) return -ENODEV; - reg = get_property(node, "reg", NULL); + reg = of_get_property(node, "reg", NULL); if (!reg) return -ENODEV; *bus = (reg[0] >> 16) & 0xff; @@ -895,14 +900,14 @@ pci_process_bridge_OF_ranges(struct pci_controller *hose, int rlen = 0, orig_rlen; int memno = 0; struct resource *res; - int np, na = prom_n_addr_cells(dev); + int np, na = of_n_addr_cells(dev); np = na + 5; /* First we try to merge ranges to fix a problem with some pmacs * that can have more than 3 ranges, fortunately using contiguous * addresses -- BenH */ - dt_ranges = get_property(dev, "ranges", &rlen); + dt_ranges = of_get_property(dev, "ranges", &rlen); if (!dt_ranges) return; /* Sanity check, though hopefully that never happens */ @@ -1006,14 +1011,19 @@ void __init pci_create_OF_bus_map(void) { struct property* of_prop; - + struct device_node *dn; + of_prop = (struct property*) alloc_bootmem(sizeof(struct property) + 256); - if (of_prop && find_path_device("/")) { + if (!of_prop) + return; + dn = of_find_node_by_path("/"); + if (dn) { memset(of_prop, -1, sizeof(struct property) + 256); of_prop->name = "pci-OF-bus-map"; of_prop->length = 256; - of_prop->value = (unsigned char *)&of_prop[1]; - prom_add_property(find_path_device("/"), of_prop); + of_prop->value = &of_prop[1]; + prom_add_property(dn, of_prop); + of_node_put(dn); } } diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 7e97d71..60d7d4b 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -61,8 +61,7 @@ void iSeries_pcibios_init(void); LIST_HEAD(hose_list); -struct dma_mapping_ops *pci_dma_ops; -EXPORT_SYMBOL(pci_dma_ops); +static struct dma_mapping_ops *pci_dma_ops; int global_phb_number; /* Global phb counter */ @@ -70,6 +69,17 @@ int global_phb_number; /* Global phb counter */ struct pci_dev *ppc64_isabridge_dev = NULL; EXPORT_SYMBOL_GPL(ppc64_isabridge_dev); +void set_pci_dma_ops(struct dma_mapping_ops *dma_ops) +{ + pci_dma_ops = dma_ops; +} + +struct dma_mapping_ops *get_pci_dma_ops(void) +{ + return pci_dma_ops; +} +EXPORT_SYMBOL(get_pci_dma_ops); + static void fixup_broken_pcnet32(struct pci_dev* dev) { if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) { @@ -258,7 +268,7 @@ static u32 get_int_prop(struct device_node *np, const char *name, u32 def) const u32 *prop; int len; - prop = get_property(np, name, &len); + prop = of_get_property(np, name, &len); if (prop && len >= 4) return *prop; return def; @@ -291,7 +301,7 @@ static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev) u32 i; int proplen; - addrs = get_property(node, "assigned-addresses", &proplen); + addrs = of_get_property(node, "assigned-addresses", &proplen); if (!addrs) return; DBG(" parse addresses (%d bytes) @ %p\n", proplen, addrs); @@ -333,7 +343,7 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL); if (!dev) return NULL; - type = get_property(node, "device_type", NULL); + type = of_get_property(node, "device_type", NULL); if (type == NULL) type = ""; @@ -397,7 +407,7 @@ void __devinit of_scan_bus(struct device_node *node, while ((child = of_get_next_child(node, child)) != NULL) { DBG(" * %s\n", child->full_name); - reg = get_property(child, "reg", ®len); + reg = of_get_property(child, "reg", ®len); if (reg == NULL || reglen < 20) continue; devfn = (reg[0] >> 8) & 0xff; @@ -430,13 +440,13 @@ void __devinit of_scan_pci_bridge(struct device_node *node, DBG("of_scan_pci_bridge(%s)\n", node->full_name); /* parse bus-range property */ - busrange = get_property(node, "bus-range", &len); + busrange = of_get_property(node, "bus-range", &len); if (busrange == NULL || len != 8) { printk(KERN_DEBUG "Can't get bus-range for PCI-PCI bridge %s\n", node->full_name); return; } - ranges = get_property(node, "ranges", &len); + ranges = of_get_property(node, "ranges", &len); if (ranges == NULL) { printk(KERN_DEBUG "Can't get ranges for PCI-PCI bridge %s\n", node->full_name); @@ -900,7 +910,7 @@ static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node, unsigned int size; int rlen = 0; - range = get_property(isa_node, "ranges", &rlen); + range = of_get_property(isa_node, "ranges", &rlen); if (range == NULL || (rlen < sizeof(struct isa_range))) { printk(KERN_ERR "no ISA ranges or unexpected isa range size," "mapping 64k\n"); @@ -947,7 +957,7 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose, int rlen = 0; int memno = 0; struct resource *res; - int np, na = prom_n_addr_cells(dev); + int np, na = of_n_addr_cells(dev); unsigned long pci_addr, cpu_phys_addr; np = na + 5; @@ -960,7 +970,7 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose, * (size depending on dev->n_addr_cells) * cells 4+5 or 5+6: the size of the range */ - ranges = get_property(dev, "ranges", &rlen); + ranges = of_get_property(dev, "ranges", &rlen); if (ranges == NULL) return; hose->io_base_phys = 0; diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c index 68df018..d7d36df 100644 --- a/arch/powerpc/kernel/pci_dn.c +++ b/arch/powerpc/kernel/pci_dn.c @@ -40,7 +40,8 @@ static void * __devinit update_dn_pci_info(struct device_node *dn, void *data) { struct pci_controller *phb = data; - const int *type = get_property(dn, "ibm,pci-config-space-type", NULL); + const int *type = + of_get_property(dn, "ibm,pci-config-space-type", NULL); const u32 *regs; struct pci_dn *pdn; @@ -54,14 +55,14 @@ static void * __devinit update_dn_pci_info(struct device_node *dn, void *data) dn->data = pdn; pdn->node = dn; pdn->phb = phb; - regs = get_property(dn, "reg", NULL); + regs = of_get_property(dn, "reg", NULL); if (regs) { /* First register entry is addr (00BBSS00) */ pdn->busno = (regs[0] >> 16) & 0xff; pdn->devfn = (regs[0] >> 8) & 0xff; } if (firmware_has_feature(FW_FEATURE_ISERIES)) { - const u32 *busp = get_property(dn, "linux,subbus", NULL); + const u32 *busp = of_get_property(dn, "linux,subbus", NULL); if (busp) pdn->bussubno = *busp; } @@ -100,7 +101,7 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre, u32 class; nextdn = NULL; - classp = get_property(dn, "class-code", NULL); + classp = of_get_property(dn, "class-code", NULL); class = classp ? *classp : 0; if (pre && ((ret = pre(dn, data)) != NULL)) diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index 2f8e9c0..ff252aa 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c @@ -20,7 +20,6 @@ #include <asm/processor.h> #include <asm/uaccess.h> #include <asm/io.h> -#include <asm/ide.h> #include <asm/atomic.h> #include <asm/checksum.h> #include <asm/pgtable.h> diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index e53b298..e509aae 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -305,9 +305,7 @@ struct task_struct *__switch_to(struct task_struct *prev, set_dabr(new->thread.dabr); __get_cpu_var(current_dabr) = new->thread.dabr; } - - flush_tlb_pending(); -#endif +#endif /* CONFIG_PPC64 */ new_thread = &new->thread; old_thread = ¤t->thread; @@ -402,11 +400,11 @@ static void printbits(unsigned long val, struct regbit *bits) } #ifdef CONFIG_PPC64 -#define REG "%016lX" +#define REG "%016lx" #define REGS_PER_LINE 4 #define LAST_VOLATILE 13 #else -#define REG "%08lX" +#define REG "%08lx" #define REGS_PER_LINE 8 #define LAST_VOLATILE 12 #endif @@ -421,7 +419,7 @@ void show_regs(struct pt_regs * regs) regs, regs->trap, print_tainted(), init_utsname()->release); printk("MSR: "REG" ", regs->msr); printbits(regs->msr, msr_bits); - printk(" CR: %08lX XER: %08lX\n", regs->ccr, regs->xer); + printk(" CR: %08lx XER: %08lx\n", regs->ccr, regs->xer); trap = TRAP(regs); if (trap == 0x300 || trap == 0x600) printk("DAR: "REG", DSISR: "REG"\n", regs->dar, regs->dsisr); @@ -572,7 +570,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, kregs->nip = *((unsigned long *)ret_from_fork); #else kregs->nip = (unsigned long)ret_from_fork; - p->thread.last_syscall = -1; #endif return 0; @@ -823,6 +820,35 @@ out: return error; } +#ifdef CONFIG_IRQSTACKS +static inline int valid_irq_stack(unsigned long sp, struct task_struct *p, + unsigned long nbytes) +{ + unsigned long stack_page; + unsigned long cpu = task_cpu(p); + + /* + * Avoid crashing if the stack has overflowed and corrupted + * task_cpu(p), which is in the thread_info struct. + */ + if (cpu < NR_CPUS && cpu_possible(cpu)) { + stack_page = (unsigned long) hardirq_ctx[cpu]; + if (sp >= stack_page + sizeof(struct thread_struct) + && sp <= stack_page + THREAD_SIZE - nbytes) + return 1; + + stack_page = (unsigned long) softirq_ctx[cpu]; + if (sp >= stack_page + sizeof(struct thread_struct) + && sp <= stack_page + THREAD_SIZE - nbytes) + return 1; + } + return 0; +} + +#else +#define valid_irq_stack(sp, p, nb) 0 +#endif /* CONFIG_IRQSTACKS */ + int validate_sp(unsigned long sp, struct task_struct *p, unsigned long nbytes) { @@ -832,19 +858,7 @@ int validate_sp(unsigned long sp, struct task_struct *p, && sp <= stack_page + THREAD_SIZE - nbytes) return 1; -#ifdef CONFIG_IRQSTACKS - stack_page = (unsigned long) hardirq_ctx[task_cpu(p)]; - if (sp >= stack_page + sizeof(struct thread_struct) - && sp <= stack_page + THREAD_SIZE - nbytes) - return 1; - - stack_page = (unsigned long) softirq_ctx[task_cpu(p)]; - if (sp >= stack_page + sizeof(struct thread_struct) - && sp <= stack_page + THREAD_SIZE - nbytes) - return 1; -#endif - - return 0; + return valid_irq_stack(sp, p, nbytes); } #ifdef CONFIG_PPC64 diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 8d52b23..caef555 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -390,18 +390,19 @@ static unsigned long __init unflatten_dt_node(unsigned long mem, if (allnextpp) { pp->name = "name"; pp->length = sz; - pp->value = (unsigned char *)(pp + 1); + pp->value = pp + 1; *prev_pp = pp; prev_pp = &pp->next; memcpy(pp->value, ps, sz - 1); ((char *)pp->value)[sz - 1] = 0; - DBG("fixed up name for %s -> %s\n", pathp, pp->value); + DBG("fixed up name for %s -> %s\n", pathp, + (char *)pp->value); } } if (allnextpp) { *prev_pp = NULL; - np->name = get_property(np, "name", NULL); - np->type = get_property(np, "device_type", NULL); + np->name = of_get_property(np, "name", NULL); + np->type = of_get_property(np, "device_type", NULL); if (!np->name) np->name = "<NULL>"; @@ -719,6 +720,7 @@ static int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, int depth, void *data) { unsigned long *lprop; + u32 *prop; unsigned long l; char *p; @@ -760,6 +762,22 @@ static int __init early_init_dt_scan_chosen(unsigned long node, crashk_res.end = crashk_res.start + *lprop - 1; #endif +#ifdef CONFIG_BLK_DEV_INITRD + DBG("Looking for initrd properties... "); + prop = of_get_flat_dt_prop(node, "linux,initrd-start", &l); + if (prop) { + initrd_start = (unsigned long)__va(of_read_ulong(prop, l/4)); + prop = of_get_flat_dt_prop(node, "linux,initrd-end", &l); + if (prop) { + initrd_end = (unsigned long)__va(of_read_ulong(prop, l/4)); + initrd_below_start_ok = 1; + } else { + initrd_start = 0; + } + } + DBG("initrd_start=0x%lx initrd_end=0x%lx\n", initrd_start, initrd_end); +#endif /* CONFIG_BLK_DEV_INITRD */ + /* Retreive command line */ p = of_get_flat_dt_prop(node, "bootargs", &l); if (p != NULL && l > 0) @@ -926,6 +944,12 @@ static void __init early_reserve_mem(void) self_size = initial_boot_params->totalsize; lmb_reserve(self_base, self_size); +#ifdef CONFIG_BLK_DEV_INITRD + /* then reserve the initrd, if any */ + if (initrd_start && (initrd_end > initrd_start)) + lmb_reserve(__pa(initrd_start), initrd_end - initrd_start); +#endif /* CONFIG_BLK_DEV_INITRD */ + #ifdef CONFIG_PPC32 /* * Handle the case where we might be booting from an old kexec @@ -954,9 +978,6 @@ static void __init early_reserve_mem(void) size = *(reserve_map++); if (size == 0) break; - /* skip if the reservation is for the blob */ - if (base == self_base && size == self_size) - continue; DBG("reserving: %llx -> %llx\n", base, size); lmb_reserve(base, size); } @@ -1021,102 +1042,46 @@ void __init early_init_devtree(void *params) #undef printk -int -prom_n_addr_cells(struct device_node* np) +int of_n_addr_cells(struct device_node* np) { const int *ip; do { if (np->parent) np = np->parent; - ip = get_property(np, "#address-cells", NULL); + ip = of_get_property(np, "#address-cells", NULL); if (ip != NULL) return *ip; } while (np->parent); /* No #address-cells property for the root node, default to 1 */ return 1; } -EXPORT_SYMBOL(prom_n_addr_cells); +EXPORT_SYMBOL(of_n_addr_cells); -int -prom_n_size_cells(struct device_node* np) +int of_n_size_cells(struct device_node* np) { const int* ip; do { if (np->parent) np = np->parent; - ip = get_property(np, "#size-cells", NULL); + ip = of_get_property(np, "#size-cells", NULL); if (ip != NULL) return *ip; } while (np->parent); /* No #size-cells property for the root node, default to 1 */ return 1; } -EXPORT_SYMBOL(prom_n_size_cells); - -/** - * Construct and return a list of the device_nodes with a given name. - */ -struct device_node *find_devices(const char *name) -{ - struct device_node *head, **prevp, *np; - - prevp = &head; - for (np = allnodes; np != 0; np = np->allnext) { - if (np->name != 0 && strcasecmp(np->name, name) == 0) { - *prevp = np; - prevp = &np->next; - } - } - *prevp = NULL; - return head; -} -EXPORT_SYMBOL(find_devices); - -/** - * Construct and return a list of the device_nodes with a given type. - */ -struct device_node *find_type_devices(const char *type) -{ - struct device_node *head, **prevp, *np; - - prevp = &head; - for (np = allnodes; np != 0; np = np->allnext) { - if (np->type != 0 && strcasecmp(np->type, type) == 0) { - *prevp = np; - prevp = &np->next; - } - } - *prevp = NULL; - return head; -} -EXPORT_SYMBOL(find_type_devices); - -/** - * Returns all nodes linked together - */ -struct device_node *find_all_nodes(void) -{ - struct device_node *head, **prevp, *np; - - prevp = &head; - for (np = allnodes; np != 0; np = np->allnext) { - *prevp = np; - prevp = &np->next; - } - *prevp = NULL; - return head; -} -EXPORT_SYMBOL(find_all_nodes); +EXPORT_SYMBOL(of_n_size_cells); /** Checks if the given "compat" string matches one of the strings in * the device's "compatible" property */ -int device_is_compatible(const struct device_node *device, const char *compat) +int of_device_is_compatible(const struct device_node *device, + const char *compat) { const char* cp; int cplen, l; - cp = get_property(device, "compatible", &cplen); + cp = of_get_property(device, "compatible", &cplen); if (cp == NULL) return 0; while (cplen > 0) { @@ -1129,7 +1094,7 @@ int device_is_compatible(const struct device_node *device, const char *compat) return 0; } -EXPORT_SYMBOL(device_is_compatible); +EXPORT_SYMBOL(of_device_is_compatible); /** @@ -1143,51 +1108,13 @@ int machine_is_compatible(const char *compat) root = of_find_node_by_path("/"); if (root) { - rc = device_is_compatible(root, compat); + rc = of_device_is_compatible(root, compat); of_node_put(root); } return rc; } EXPORT_SYMBOL(machine_is_compatible); -/** - * Construct and return a list of the device_nodes with a given type - * and compatible property. - */ -struct device_node *find_compatible_devices(const char *type, - const char *compat) -{ - struct device_node *head, **prevp, *np; - - prevp = &head; - for (np = allnodes; np != 0; np = np->allnext) { - if (type != NULL - && !(np->type != 0 && strcasecmp(np->type, type) == 0)) - continue; - if (device_is_compatible(np, compat)) { - *prevp = np; - prevp = &np->next; - } - } - *prevp = NULL; - return head; -} -EXPORT_SYMBOL(find_compatible_devices); - -/** - * Find the device_node with a given full_name. - */ -struct device_node *find_path_device(const char *path) -{ - struct device_node *np; - - for (np = allnodes; np != 0; np = np->allnext) - if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0) - return np; - return NULL; -} -EXPORT_SYMBOL(find_path_device); - /******* * * New implementation of the OF "find" APIs, return a refcounted @@ -1280,7 +1207,7 @@ struct device_node *of_find_compatible_node(struct device_node *from, if (type != NULL && !(np->type != 0 && strcasecmp(np->type, type) == 0)) continue; - if (device_is_compatible(np, compatible) && of_node_get(np)) + if (of_device_is_compatible(np, compatible) && of_node_get(np)) break; } of_node_put(from); @@ -1527,8 +1454,8 @@ static int of_finish_dynamic_node(struct device_node *node) int err = 0; const phandle *ibm_phandle; - node->name = get_property(node, "name", NULL); - node->type = get_property(node, "device_type", NULL); + node->name = of_get_property(node, "name", NULL); + node->type = of_get_property(node, "device_type", NULL); if (!parent) { err = -ENODEV; @@ -1542,7 +1469,7 @@ static int of_finish_dynamic_node(struct device_node *node) return -ENODEV; /* fix up new node's linux_phandle field */ - if ((ibm_phandle = get_property(node, "ibm,phandle", NULL))) + if ((ibm_phandle = of_get_property(node, "ibm,phandle", NULL))) node->linux_phandle = *ibm_phandle; out: @@ -1605,13 +1532,13 @@ EXPORT_SYMBOL(of_find_property); * Find a property with a given name for a given node * and return the value. */ -const void *get_property(const struct device_node *np, const char *name, +const void *of_get_property(const struct device_node *np, const char *name, int *lenp) { struct property *pp = of_find_property(np,name,lenp); return pp ? pp->value : NULL; } -EXPORT_SYMBOL(get_property); +EXPORT_SYMBOL(of_get_property); /* * Add a property to a node @@ -1742,10 +1669,10 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) /* Check for ibm,ppc-interrupt-server#s. If it doesn't exist * fallback to "reg" property and assume no threads */ - intserv = get_property(np, "ibm,ppc-interrupt-server#s", + intserv = of_get_property(np, "ibm,ppc-interrupt-server#s", &plen); if (intserv == NULL) { - const u32 *reg = get_property(np, "reg", NULL); + const u32 *reg = of_get_property(np, "reg", NULL); if (reg == NULL) continue; if (*reg == hardid) { diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 4fb5938..e27d9d1 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -2035,39 +2035,50 @@ static void __init fixup_device_tree_maple(void) #endif #ifdef CONFIG_PPC_CHRP -/* Pegasos and BriQ lacks the "ranges" property in the isa node */ +/* + * Pegasos and BriQ lacks the "ranges" property in the isa node + * Pegasos needs decimal IRQ 14/15, not hexadecimal + */ static void __init fixup_device_tree_chrp(void) { - phandle isa; - u32 isa_ranges[6]; + phandle ph; + u32 prop[6]; u32 rloc = 0x01006000; /* IO space; PCI device = 12 */ char *name; int rc; name = "/pci@80000000/isa@c"; - isa = call_prom("finddevice", 1, 1, ADDR(name)); - if (!PHANDLE_VALID(isa)) { + ph = call_prom("finddevice", 1, 1, ADDR(name)); + if (!PHANDLE_VALID(ph)) { name = "/pci@ff500000/isa@6"; - isa = call_prom("finddevice", 1, 1, ADDR(name)); + ph = call_prom("finddevice", 1, 1, ADDR(name)); rloc = 0x01003000; /* IO space; PCI device = 6 */ } - if (!PHANDLE_VALID(isa)) - return; - - rc = prom_getproplen(isa, "ranges"); - if (rc != 0 && rc != PROM_ERROR) - return; - - prom_printf("Fixing up missing ISA range on Pegasos...\n"); + if (PHANDLE_VALID(ph)) { + rc = prom_getproplen(ph, "ranges"); + if (rc == 0 || rc == PROM_ERROR) { + prom_printf("Fixing up missing ISA range on Pegasos...\n"); + + prop[0] = 0x1; + prop[1] = 0x0; + prop[2] = rloc; + prop[3] = 0x0; + prop[4] = 0x0; + prop[5] = 0x00010000; + prom_setprop(ph, name, "ranges", prop, sizeof(prop)); + } + } - isa_ranges[0] = 0x1; - isa_ranges[1] = 0x0; - isa_ranges[2] = rloc; - isa_ranges[3] = 0x0; - isa_ranges[4] = 0x0; - isa_ranges[5] = 0x00010000; - prom_setprop(isa, name, "ranges", - isa_ranges, sizeof(isa_ranges)); + name = "/pci@80000000/ide@C,1"; + ph = call_prom("finddevice", 1, 1, ADDR(name)); + if (PHANDLE_VALID(ph)) { + prom_printf("Fixing up IDE interrupt on Pegasos...\n"); + prop[0] = 14; + prop[1] = 0x0; + prop[2] = 15; + prop[3] = 0x0; + prom_setprop(ph, name, "interrupts", prop, 4*sizeof(u32)); + } } #else #define fixup_device_tree_chrp() diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c index 91b443c..aa40a53 100644 --- a/arch/powerpc/kernel/prom_parse.c +++ b/arch/powerpc/kernel/prom_parse.c @@ -68,9 +68,9 @@ static void of_bus_default_count_cells(struct device_node *dev, int *addrc, int *sizec) { if (addrc) - *addrc = prom_n_addr_cells(dev); + *addrc = of_n_addr_cells(dev); if (sizec) - *sizec = prom_n_size_cells(dev); + *sizec = of_n_size_cells(dev); } static u64 of_bus_default_map(u32 *addr, const u32 *range, @@ -196,7 +196,7 @@ const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size, return NULL; /* Get "reg" or "assigned-addresses" property */ - prop = get_property(dev, bus->addresses, &psize); + prop = of_get_property(dev, bus->addresses, &psize); if (prop == NULL) return NULL; psize /= 4; @@ -438,7 +438,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus, * to translate addresses that aren't supposed to be translated in * the first place. --BenH. */ - ranges = get_property(parent, "ranges", &rlen); + ranges = of_get_property(parent, "ranges", &rlen); if (ranges == NULL || rlen == 0) { offset = of_read_number(addr, na); memset(addr, 0, pna * 4); @@ -578,7 +578,7 @@ const u32 *of_get_address(struct device_node *dev, int index, u64 *size, return NULL; /* Get "reg" or "assigned-addresses" property */ - prop = get_property(dev, bus->addresses, &psize); + prop = of_get_property(dev, bus->addresses, &psize); if (prop == NULL) return NULL; psize /= 4; @@ -650,17 +650,17 @@ void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, /* busno is always one cell */ *busno = *(dma_window++); - prop = get_property(dn, "ibm,#dma-address-cells", NULL); + prop = of_get_property(dn, "ibm,#dma-address-cells", NULL); if (!prop) - prop = get_property(dn, "#address-cells", NULL); + prop = of_get_property(dn, "#address-cells", NULL); - cells = prop ? *(u32 *)prop : prom_n_addr_cells(dn); + cells = prop ? *(u32 *)prop : of_n_addr_cells(dn); *phys = of_read_number(dma_window, cells); dma_window += cells; - prop = get_property(dn, "ibm,#dma-size-cells", NULL); - cells = prop ? *(u32 *)prop : prom_n_size_cells(dn); + prop = of_get_property(dn, "ibm,#dma-size-cells", NULL); + cells = prop ? *(u32 *)prop : of_n_size_cells(dn); *size = of_read_number(dma_window, cells); } @@ -680,7 +680,7 @@ static struct device_node *of_irq_find_parent(struct device_node *child) return NULL; do { - parp = get_property(child, "interrupt-parent", NULL); + parp = of_get_property(child, "interrupt-parent", NULL); if (parp == NULL) p = of_get_parent(child); else { @@ -691,7 +691,7 @@ static struct device_node *of_irq_find_parent(struct device_node *child) } of_node_put(child); child = p; - } while (p && get_property(p, "#interrupt-cells", NULL) == NULL); + } while (p && of_get_property(p, "#interrupt-cells", NULL) == NULL); return p; } @@ -716,7 +716,7 @@ void of_irq_map_init(unsigned int flags) struct device_node *np; for(np = NULL; (np = of_find_all_nodes(np)) != NULL;) { - if (get_property(np, "interrupt-controller", NULL) + if (of_get_property(np, "interrupt-controller", NULL) == NULL) continue; /* Skip /chosen/interrupt-controller */ @@ -755,7 +755,7 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize, * is none, we are nice and just walk up the tree */ do { - tmp = get_property(ipar, "#interrupt-cells", NULL); + tmp = of_get_property(ipar, "#interrupt-cells", NULL); if (tmp != NULL) { intsize = *tmp; break; @@ -779,7 +779,7 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize, */ old = of_node_get(ipar); do { - tmp = get_property(old, "#address-cells", NULL); + tmp = of_get_property(old, "#address-cells", NULL); tnode = of_get_parent(old); of_node_put(old); old = tnode; @@ -795,7 +795,8 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize, /* Now check if cursor is an interrupt-controller and if it is * then we are done */ - if (get_property(ipar, "interrupt-controller", NULL) != NULL) { + if (of_get_property(ipar, "interrupt-controller", NULL) != + NULL) { DBG(" -> got it !\n"); memcpy(out_irq->specifier, intspec, intsize * sizeof(u32)); @@ -806,7 +807,7 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize, } /* Now look for an interrupt-map */ - imap = get_property(ipar, "interrupt-map", &imaplen); + imap = of_get_property(ipar, "interrupt-map", &imaplen); /* No interrupt map, check for an interrupt parent */ if (imap == NULL) { DBG(" -> no map, getting parent\n"); @@ -816,7 +817,7 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize, imaplen /= sizeof(u32); /* Look for a mask */ - imask = get_property(ipar, "interrupt-map-mask", NULL); + imask = of_get_property(ipar, "interrupt-map-mask", NULL); /* If we were passed no "reg" property and we attempt to parse * an interrupt-map, then #address-cells must be 0. @@ -863,15 +864,13 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize, /* Get #interrupt-cells and #address-cells of new * parent */ - tmp = get_property(newpar, "#interrupt-cells", - NULL); + tmp = of_get_property(newpar, "#interrupt-cells", NULL); if (tmp == NULL) { DBG(" -> parent lacks #interrupt-cells !\n"); goto fail; } newintsize = *tmp; - tmp = get_property(newpar, "#address-cells", - NULL); + tmp = of_get_property(newpar, "#address-cells", NULL); newaddrsize = (tmp == NULL) ? 0 : *tmp; DBG(" -> newintsize=%d, newaddrsize=%d\n", @@ -928,7 +927,7 @@ static int of_irq_map_oldworld(struct device_node *device, int index, * everything together on these) */ while (device) { - ints = get_property(device, "AAPL,interrupts", &intlen); + ints = of_get_property(device, "AAPL,interrupts", &intlen); if (ints != NULL) break; device = device->parent; @@ -970,13 +969,13 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq return of_irq_map_oldworld(device, index, out_irq); /* Get the interrupts property */ - intspec = get_property(device, "interrupts", &intlen); + intspec = of_get_property(device, "interrupts", &intlen); if (intspec == NULL) return -EINVAL; intlen /= sizeof(u32); /* Get the reg property (if any) */ - addr = get_property(device, "reg", NULL); + addr = of_get_property(device, "reg", NULL); /* Look for the interrupt parent. */ p = of_irq_find_parent(device); @@ -984,7 +983,7 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq return -EINVAL; /* Get size of interrupt specifier */ - tmp = get_property(p, "#interrupt-cells", NULL); + tmp = of_get_property(p, "#interrupt-cells", NULL); if (tmp == NULL) { of_node_put(p); return -EINVAL; diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c index 6cbf2ae..190b7ed 100644 --- a/arch/powerpc/kernel/rtas-proc.c +++ b/arch/powerpc/kernel/rtas-proc.c @@ -450,7 +450,7 @@ static int ppc_rtas_sensors_show(struct seq_file *m, void *v) int llen, offs; sprintf (rstr, SENSOR_PREFIX"%04d", p->token); - loc = get_property(rtas_node, rstr, &llen); + loc = of_get_property(rtas_node, rstr, &llen); /* A sensor may have multiple instances */ for (j = 0, offs = 0; j <= p->quant; j++) { @@ -477,7 +477,7 @@ static int ppc_rtas_find_all_sensors(void) const unsigned int *utmp; int len, i; - utmp = get_property(rtas_node, "rtas-sensors", &len); + utmp = of_get_property(rtas_node, "rtas-sensors", &len); if (utmp == NULL) { printk (KERN_ERR "error: could not get rtas-sensors\n"); return 1; diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 9d0735a..2147807 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -192,18 +192,19 @@ void rtas_progress(char *s, unsigned short hex) if (display_width == 0) { display_width = 0x10; - if ((root = find_path_device("/rtas"))) { - if ((p = get_property(root, + if ((root = of_find_node_by_path("/rtas"))) { + if ((p = of_get_property(root, "ibm,display-line-length", NULL))) display_width = *p; - if ((p = get_property(root, + if ((p = of_get_property(root, "ibm,form-feed", NULL))) form_feed = *p; - if ((p = get_property(root, + if ((p = of_get_property(root, "ibm,display-number-of-lines", NULL))) display_lines = *p; - row_width = get_property(root, + row_width = of_get_property(root, "ibm,display-truncation-length", NULL); + of_node_put(root); } display_character = rtas_token("display-character"); set_indicator = rtas_token("set-indicator"); @@ -298,7 +299,7 @@ int rtas_token(const char *service) const int *tokp; if (rtas.dev == NULL) return RTAS_UNKNOWN_SERVICE; - tokp = get_property(rtas.dev, service, NULL); + tokp = of_get_property(rtas.dev, service, NULL); return tokp ? *tokp : RTAS_UNKNOWN_SERVICE; } EXPORT_SYMBOL(rtas_token); @@ -832,12 +833,12 @@ void __init rtas_initialize(void) if (rtas.dev) { const u32 *basep, *entryp, *sizep; - basep = get_property(rtas.dev, "linux,rtas-base", NULL); - sizep = get_property(rtas.dev, "rtas-size", NULL); + basep = of_get_property(rtas.dev, "linux,rtas-base", NULL); + sizep = of_get_property(rtas.dev, "rtas-size", NULL); if (basep != NULL && sizep != NULL) { rtas.base = *basep; rtas.size = *sizep; - entryp = get_property(rtas.dev, + entryp = of_get_property(rtas.dev, "linux,rtas-entry", NULL); if (entryp == NULL) /* Ugh */ rtas.entry = rtas.base; diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index ace9f4c..f228682 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c @@ -60,7 +60,7 @@ static int of_device_available(struct device_node * dn) { const char *status; - status = get_property(dn, "status", NULL); + status = of_get_property(dn, "status", NULL); if (!status) return 1; @@ -177,7 +177,7 @@ struct pci_ops rtas_pci_ops = { int is_python(struct device_node *dev) { - const char *model = get_property(dev, "model", NULL); + const char *model = of_get_property(dev, "model", NULL); if (model && strstr(model, "Python")) return 1; @@ -247,7 +247,7 @@ static int phb_set_bus_ranges(struct device_node *dev, const int *bus_range; unsigned int len; - bus_range = get_property(dev, "bus-range", &len); + bus_range = of_get_property(dev, "bus-range", &len); if (bus_range == NULL || len < 2 * sizeof(int)) { return 1; } @@ -274,7 +274,7 @@ int __devinit rtas_setup_phb(struct pci_controller *phb) return 0; } -unsigned long __init find_and_init_phbs(void) +void __init find_and_init_phbs(void) { struct device_node *node; struct pci_controller *phb; @@ -309,18 +309,16 @@ unsigned long __init find_and_init_phbs(void) if (of_chosen) { const int *prop; - prop = get_property(of_chosen, + prop = of_get_property(of_chosen, "linux,pci-probe-only", NULL); if (prop) pci_probe_only = *prop; - prop = get_property(of_chosen, + prop = of_get_property(of_chosen, "linux,pci-assign-all-buses", NULL); if (prop) pci_assign_all_buses = *prop; } - - return 0; } /* RPA-specific bits for removing PHBs */ diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 89cfaf4..3708037 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -21,7 +21,6 @@ #include <linux/delay.h> #include <linux/initrd.h> #include <linux/platform_device.h> -#include <linux/ide.h> #include <linux/seq_file.h> #include <linux/ioport.h> #include <linux/console.h> @@ -304,26 +303,8 @@ struct seq_operations cpuinfo_op = { void __init check_for_initrd(void) { #ifdef CONFIG_BLK_DEV_INITRD - const unsigned int *prop; - int len; - - DBG(" -> check_for_initrd()\n"); - - if (of_chosen) { - prop = get_property(of_chosen, "linux,initrd-start", &len); - if (prop != NULL) { - initrd_start = (unsigned long) - __va(of_read_ulong(prop, len / 4)); - prop = get_property(of_chosen, - "linux,initrd-end", &len); - if (prop != NULL) { - initrd_end = (unsigned long) - __va(of_read_ulong(prop, len / 4)); - initrd_below_start_ok = 1; - } else - initrd_start = 0; - } - } + DBG(" -> check_for_initrd() initrd_start=0x%lx initrd_end=0x%lx\n", + initrd_start, initrd_end); /* If we were passed an initrd, set the ROOT_DEV properly if the values * look sensible. If not, clear initrd reference. @@ -371,11 +352,12 @@ void __init smp_setup_cpu_maps(void) const int *intserv; int j, len = sizeof(u32), nthreads = 1; - intserv = get_property(dn, "ibm,ppc-interrupt-server#s", &len); + intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s", + &len); if (intserv) nthreads = len / sizeof(int); else { - intserv = get_property(dn, "reg", NULL); + intserv = of_get_property(dn, "reg", NULL); if (!intserv) intserv = &cpu; /* assume logical == phys */ } @@ -398,10 +380,10 @@ void __init smp_setup_cpu_maps(void) int num_addr_cell, num_size_cell, maxcpus; const unsigned int *ireg; - num_addr_cell = prom_n_addr_cells(dn); - num_size_cell = prom_n_size_cells(dn); + num_addr_cell = of_n_addr_cells(dn); + num_size_cell = of_n_size_cells(dn); - ireg = get_property(dn, "ibm,lrdr-capacity", NULL); + ireg = of_get_property(dn, "ibm,lrdr-capacity", NULL); if (!ireg) goto out; @@ -496,11 +478,39 @@ void probe_machine(void) printk(KERN_INFO "Using %s machine description\n", ppc_md.name); } +/* Match a class of boards, not a specific device configuration. */ int check_legacy_ioport(unsigned long base_port) { - if (ppc_md.check_legacy_ioport == NULL) - return 0; - return ppc_md.check_legacy_ioport(base_port); + struct device_node *parent, *np = NULL; + int ret = -ENODEV; + + switch(base_port) { + case I8042_DATA_REG: + np = of_find_node_by_type(NULL, "8042"); + break; + case FDC_BASE: /* FDC1 */ + np = of_find_node_by_type(NULL, "fdc"); + break; +#ifdef CONFIG_PPC_PREP + case _PIDXR: + case _PNPWRP: + case PNPBIOS_BASE: + /* implement me */ +#endif + default: + /* ipmi is supposed to fail here */ + break; + } + if (!np) + return ret; + parent = of_get_parent(np); + if (parent) { + if (strcmp(parent->type, "isa") == 0) + ret = 0; + of_node_put(parent); + } + of_node_put(np); + return ret; } EXPORT_SYMBOL(check_legacy_ioport); diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 44a6a3c..35f8f44 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -92,7 +92,8 @@ unsigned long __init early_init(unsigned long dt_ptr) /* First zero the BSS -- use memset_io, some platforms don't have * caches on yet */ - memset_io((void __iomem *)PTRRELOC(&__bss_start), 0, _end - __bss_start); + memset_io((void __iomem *)PTRRELOC(&__bss_start), 0, + __bss_stop - __bss_start); /* * Identify the CPU type and fix up code sections @@ -195,18 +196,22 @@ EXPORT_SYMBOL(nvram_sync); #endif /* CONFIG_NVRAM */ -static struct cpu cpu_devices[NR_CPUS]; +static DEFINE_PER_CPU(struct cpu, cpu_devices); int __init ppc_init(void) { - int i; + int cpu; /* clear the progress line */ - if ( ppc_md.progress ) ppc_md.progress(" ", 0xffff); + if (ppc_md.progress) + ppc_md.progress(" ", 0xffff); /* register CPU devices */ - for_each_possible_cpu(i) - register_cpu(&cpu_devices[i], i); + for_each_possible_cpu(cpu) { + struct cpu *c = &per_cpu(cpu_devices, cpu); + c->hotpluggable = 1; + register_cpu(c, cpu); + } /* call platform init */ if (ppc_md.init != NULL) { diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 3733de3..22083ce 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -20,7 +20,6 @@ #include <linux/reboot.h> #include <linux/delay.h> #include <linux/initrd.h> -#include <linux/ide.h> #include <linux/seq_file.h> #include <linux/ioport.h> #include <linux/console.h> @@ -110,7 +109,7 @@ static void check_smt_enabled(void) dn = of_find_node_by_path("/options"); if (dn) { - smt_option = get_property(dn, "ibm,smt-enabled", NULL); + smt_option = of_get_property(dn, "ibm,smt-enabled", NULL); if (smt_option) { if (!strcmp(smt_option, "on")) @@ -305,10 +304,10 @@ static void __init initialize_cache_info(void) size = 0; lsize = cur_cpu_spec->dcache_bsize; - sizep = get_property(np, "d-cache-size", NULL); + sizep = of_get_property(np, "d-cache-size", NULL); if (sizep != NULL) size = *sizep; - lsizep = get_property(np, dc, NULL); + lsizep = of_get_property(np, dc, NULL); if (lsizep != NULL) lsize = *lsizep; if (sizep == 0 || lsizep == 0) @@ -322,10 +321,10 @@ static void __init initialize_cache_info(void) size = 0; lsize = cur_cpu_spec->icache_bsize; - sizep = get_property(np, "i-cache-size", NULL); + sizep = of_get_property(np, "i-cache-size", NULL); if (sizep != NULL) size = *sizep; - lsizep = get_property(np, ic, NULL); + lsizep = of_get_property(np, ic, NULL); if (lsizep != NULL) lsize = *lsizep; if (sizep == 0 || lsizep == 0) diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 924d692..d8e503b 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -428,10 +428,6 @@ void generic_mach_cpu_die(void) smp_wmb(); while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE) cpu_relax(); - -#ifdef CONFIG_PPC64 - flush_tlb_pending(); -#endif cpu_set(cpu, cpu_online_map); local_irq_enable(); } diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c index 673e8d9..047246a 100644 --- a/arch/powerpc/kernel/sys_ppc32.c +++ b/arch/powerpc/kernel/sys_ppc32.c @@ -53,10 +53,6 @@ #include <asm/ppc-pci.h> #include <asm/syscalls.h> -/* readdir & getdents */ -#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de))) -#define ROUND_UP(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1)) - struct old_linux_dirent32 { u32 d_ino; u32 d_offset; diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index d57818a..933e214 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c @@ -66,16 +66,17 @@ static int __init smt_setup(void) if (!cpu_has_feature(CPU_FTR_SMT)) return -ENODEV; - options = find_path_device("/options"); + options = of_find_node_by_path("/options"); if (!options) return -ENODEV; - val = get_property(options, "ibm,smt-snooze-delay", NULL); + val = of_get_property(options, "ibm,smt-snooze-delay", NULL); if (!smt_snooze_cmdline && val) { for_each_possible_cpu(cpu) per_cpu(smt_snooze_delay, cpu) = *val; } + of_node_put(options); return 0; } __initcall(smt_setup); @@ -189,12 +190,12 @@ SYSFS_PMCSETUP(purr, SPRN_PURR); SYSFS_PMCSETUP(spurr, SPRN_SPURR); SYSFS_PMCSETUP(dscr, SPRN_DSCR); -SYSFS_PMCSETUP(pa6t_pmc0, PA6T_SPRN_PMC0); -SYSFS_PMCSETUP(pa6t_pmc1, PA6T_SPRN_PMC1); -SYSFS_PMCSETUP(pa6t_pmc2, PA6T_SPRN_PMC2); -SYSFS_PMCSETUP(pa6t_pmc3, PA6T_SPRN_PMC3); -SYSFS_PMCSETUP(pa6t_pmc4, PA6T_SPRN_PMC4); -SYSFS_PMCSETUP(pa6t_pmc5, PA6T_SPRN_PMC5); +SYSFS_PMCSETUP(pa6t_pmc0, SPRN_PA6T_PMC0); +SYSFS_PMCSETUP(pa6t_pmc1, SPRN_PA6T_PMC1); +SYSFS_PMCSETUP(pa6t_pmc2, SPRN_PA6T_PMC2); +SYSFS_PMCSETUP(pa6t_pmc3, SPRN_PA6T_PMC3); +SYSFS_PMCSETUP(pa6t_pmc4, SPRN_PA6T_PMC4); +SYSFS_PMCSETUP(pa6t_pmc5, SPRN_PA6T_PMC5); static SYSDEV_ATTR(mmcra, 0600, show_mmcra, store_mmcra); diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index f6f0c6b..7cedef8 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -834,7 +834,7 @@ static int __init get_freq(char *name, int cells, unsigned long *val) cpu = of_find_node_by_type(NULL, "cpu"); if (cpu) { - fp = get_property(cpu, name, NULL); + fp = of_get_property(cpu, name, NULL); if (fp) { found = 1; *val = of_read_ulong(fp, cells); diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 17724fb..f786222 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -90,21 +90,11 @@ EXPORT_SYMBOL(unregister_die_notifier); * Trap & Exception support */ -static DEFINE_SPINLOCK(die_lock); - -int die(const char *str, struct pt_regs *regs, long err) -{ - static int die_counter; - - if (debugger(regs)) - return 1; - - console_verbose(); - spin_lock_irq(&die_lock); - bust_spinlocks(1); #ifdef CONFIG_PMAC_BACKLIGHT +static void pmac_backlight_unblank(void) +{ mutex_lock(&pmac_backlight_mutex); - if (machine_is(powermac) && pmac_backlight) { + if (pmac_backlight) { struct backlight_properties *props; props = &pmac_backlight->props; @@ -113,26 +103,67 @@ int die(const char *str, struct pt_regs *regs, long err) backlight_update_status(pmac_backlight); } mutex_unlock(&pmac_backlight_mutex); +} +#else +static inline void pmac_backlight_unblank(void) { } #endif - printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter); + +int die(const char *str, struct pt_regs *regs, long err) +{ + static struct { + spinlock_t lock; + u32 lock_owner; + int lock_owner_depth; + } die = { + .lock = __SPIN_LOCK_UNLOCKED(die.lock), + .lock_owner = -1, + .lock_owner_depth = 0 + }; + static int die_counter; + unsigned long flags; + + if (debugger(regs)) + return 1; + + oops_enter(); + + if (die.lock_owner != raw_smp_processor_id()) { + console_verbose(); + spin_lock_irqsave(&die.lock, flags); + die.lock_owner = smp_processor_id(); + die.lock_owner_depth = 0; + bust_spinlocks(1); + if (machine_is(powermac)) + pmac_backlight_unblank(); + } else { + local_save_flags(flags); + } + + if (++die.lock_owner_depth < 3) { + printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter); #ifdef CONFIG_PREEMPT - printk("PREEMPT "); + printk("PREEMPT "); #endif #ifdef CONFIG_SMP - printk("SMP NR_CPUS=%d ", NR_CPUS); + printk("SMP NR_CPUS=%d ", NR_CPUS); #endif #ifdef CONFIG_DEBUG_PAGEALLOC - printk("DEBUG_PAGEALLOC "); + printk("DEBUG_PAGEALLOC "); #endif #ifdef CONFIG_NUMA - printk("NUMA "); + printk("NUMA "); #endif - printk("%s\n", ppc_md.name ? "" : ppc_md.name); + printk("%s\n", ppc_md.name ? ppc_md.name : ""); + + print_modules(); + show_regs(regs); + } else { + printk("Recursive die() failure, output suppressed\n"); + } - print_modules(); - show_regs(regs); bust_spinlocks(0); - spin_unlock_irq(&die_lock); + die.lock_owner = -1; + spin_unlock_irqrestore(&die.lock, flags); if (kexec_should_crash(current) || kexec_sr_activated(smp_processor_id())) @@ -145,6 +176,7 @@ int die(const char *str, struct pt_regs *regs, long err) if (panic_on_oops) panic("Fatal exception"); + oops_exit(); do_exit(err); return 0; diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index 2968ffe..9eaefac 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -81,7 +81,7 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) struct iommu_table *tbl; unsigned long offset, size; - dma_window = get_property(dev->dev.archdata.of_node, + dma_window = of_get_property(dev->dev.archdata.of_node, "ibm,my-dma-window", NULL); if (!dma_window) return NULL; @@ -226,7 +226,7 @@ struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node) return NULL; } - unit_address = get_property(of_node, "reg", NULL); + unit_address = of_get_property(of_node, "reg", NULL); if (unit_address == NULL) { printk(KERN_WARNING "%s: node %s missing 'reg'\n", __FUNCTION__, @@ -246,7 +246,7 @@ struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node) viodev->type = of_node->type; viodev->unit_address = *unit_address; if (firmware_has_feature(FW_FEATURE_ISERIES)) { - unit_address = get_property(of_node, + unit_address = of_get_property(of_node, "linux,unit_address", NULL); if (unit_address != NULL) viodev->unit_address = *unit_address; @@ -308,7 +308,7 @@ static int __init vio_bus_init(void) return err; } - node_vroot = find_devices("vdevice"); + node_vroot = of_find_node_by_name(NULL, "vdevice"); if (node_vroot) { struct device_node *of_node; @@ -322,6 +322,7 @@ static int __init vio_bus_init(void) __FUNCTION__, of_node); vio_register_device_node(of_node); } + of_node_put(node_vroot); } return 0; @@ -377,7 +378,7 @@ static int vio_hotplug(struct device *dev, char **envp, int num_envp, dn = dev->archdata.of_node; if (!dn) return -ENODEV; - cp = get_property(dn, "compatible", &length); + cp = of_get_property(dn, "compatible", &length); if (!cp) return -ENODEV; @@ -406,12 +407,12 @@ struct bus_type vio_bus_type = { * @which: The property/attribute to be extracted. * @length: Pointer to length of returned data size (unused if NULL). * - * Calls prom.c's get_property() to return the value of the + * Calls prom.c's of_get_property() to return the value of the * attribute specified by @which */ const void *vio_get_attribute(struct vio_dev *vdev, char *which, int *length) { - return get_property(vdev->dev.archdata.of_node, which, length); + return of_get_property(vdev->dev.archdata.of_node, which, length); } EXPORT_SYMBOL(vio_get_attribute); @@ -443,7 +444,7 @@ struct vio_dev *vio_find_node(struct device_node *vnode) char kobj_name[BUS_ID_SIZE]; /* construct the kobject name from the device node */ - unit_address = get_property(vnode, "reg", NULL); + unit_address = of_get_property(vnode, "reg", NULL); if (!unit_address) return NULL; snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address); diff --git a/arch/powerpc/lib/copyuser_64.S b/arch/powerpc/lib/copyuser_64.S index a6b54cb..25ec537 100644 --- a/arch/powerpc/lib/copyuser_64.S +++ b/arch/powerpc/lib/copyuser_64.S @@ -24,7 +24,7 @@ _GLOBAL(__copy_tofrom_user) dcbt 0,r4 beq .Lcopy_page_4K andi. r6,r6,7 - mtcrf 0x01,r5 + PPC_MTOCRF 0x01,r5 blt cr1,.Lshort_copy bne .Ldst_unaligned .Ldst_aligned: @@ -135,7 +135,7 @@ _GLOBAL(__copy_tofrom_user) b .Ldo_tail .Ldst_unaligned: - mtcrf 0x01,r6 /* put #bytes to 8B bdry into cr7 */ + PPC_MTOCRF 0x01,r6 /* put #bytes to 8B bdry into cr7 */ subf r5,r6,r5 li r7,0 cmpldi r1,r5,16 @@ -150,7 +150,7 @@ _GLOBAL(__copy_tofrom_user) 2: bf cr7*4+1,3f 37: lwzx r0,r7,r4 83: stwx r0,r7,r3 -3: mtcrf 0x01,r5 +3: PPC_MTOCRF 0x01,r5 add r4,r6,r4 add r3,r6,r3 b .Ldst_aligned diff --git a/arch/powerpc/lib/locks.c b/arch/powerpc/lib/locks.c index 80b482c..79d0fa3 100644 --- a/arch/powerpc/lib/locks.c +++ b/arch/powerpc/lib/locks.c @@ -43,9 +43,11 @@ void __spin_yield(raw_spinlock_t *lock) if (firmware_has_feature(FW_FEATURE_ISERIES)) HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc, ((u64)holder_cpu << 32) | yield_count); +#ifdef CONFIG_PPC_SPLPAR else plpar_hcall_norets(H_CONFER, get_hard_smp_processor_id(holder_cpu), yield_count); +#endif } /* @@ -72,9 +74,11 @@ void __rw_yield(raw_rwlock_t *rw) if (firmware_has_feature(FW_FEATURE_ISERIES)) HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc, ((u64)holder_cpu << 32) | yield_count); +#ifdef CONFIG_PPC_SPLPAR else plpar_hcall_norets(H_CONFER, get_hard_smp_processor_id(holder_cpu), yield_count); +#endif } #endif diff --git a/arch/powerpc/lib/mem_64.S b/arch/powerpc/lib/mem_64.S index 68df202..11ce045 100644 --- a/arch/powerpc/lib/mem_64.S +++ b/arch/powerpc/lib/mem_64.S @@ -19,7 +19,7 @@ _GLOBAL(memset) rlwimi r4,r4,16,0,15 cmplw cr1,r5,r0 /* do we get that far? */ rldimi r4,r4,32,0 - mtcrf 1,r0 + PPC_MTOCRF 1,r0 mr r6,r3 blt cr1,8f beq+ 3f /* if already 8-byte aligned */ @@ -49,7 +49,7 @@ _GLOBAL(memset) bdnz 4b 5: srwi. r0,r5,3 clrlwi r5,r5,29 - mtcrf 1,r0 + PPC_MTOCRF 1,r0 beq 8f bf 29,6f std r4,0(r6) @@ -65,7 +65,7 @@ _GLOBAL(memset) std r4,0(r6) addi r6,r6,8 8: cmpwi r5,0 - mtcrf 1,r5 + PPC_MTOCRF 1,r5 beqlr+ bf 29,9f stw r4,0(r6) diff --git a/arch/powerpc/lib/memcpy_64.S b/arch/powerpc/lib/memcpy_64.S index 7173ba9..3f13112 100644 --- a/arch/powerpc/lib/memcpy_64.S +++ b/arch/powerpc/lib/memcpy_64.S @@ -12,7 +12,7 @@ .align 7 _GLOBAL(memcpy) std r3,48(r1) /* save destination pointer for return value */ - mtcrf 0x01,r5 + PPC_MTOCRF 0x01,r5 cmpldi cr1,r5,16 neg r6,r3 # LS 3 bits = # bytes to 8-byte dest bdry andi. r6,r6,7 @@ -128,7 +128,7 @@ _GLOBAL(memcpy) b .Ldo_tail .Ldst_unaligned: - mtcrf 0x01,r6 # put #bytes to 8B bdry into cr7 + PPC_MTOCRF 0x01,r6 # put #bytes to 8B bdry into cr7 subf r5,r6,r5 li r7,0 cmpldi r1,r5,16 @@ -143,7 +143,7 @@ _GLOBAL(memcpy) 2: bf cr7*4+1,3f lwzx r0,r7,r4 stwx r0,r7,r3 -3: mtcrf 0x01,r5 +3: PPC_MTOCRF 0x01,r5 add r4,r6,r4 add r3,r6,r3 b .Ldst_aligned diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index 7e8ded0..4aae0c3 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c @@ -54,7 +54,7 @@ static int __kprobes branch_taken(unsigned int instr, struct pt_regs *regs) */ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) { - unsigned int opcode, rd; + unsigned int opcode, rs, rb, rd, spr; unsigned long int imm; opcode = instr >> 26; @@ -152,6 +152,49 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) regs->nip &= 0xffffffffUL; return 1; #endif + case 0x26: /* mfcr */ + regs->gpr[rd] = regs->ccr; + regs->gpr[rd] &= 0xffffffffUL; + goto mtspr_out; + case 0x2a6: /* mfspr */ + spr = (instr >> 11) & 0x3ff; + switch (spr) { + case 0x20: /* mfxer */ + regs->gpr[rd] = regs->xer; + regs->gpr[rd] &= 0xffffffffUL; + goto mtspr_out; + case 0x100: /* mflr */ + regs->gpr[rd] = regs->link; + goto mtspr_out; + case 0x120: /* mfctr */ + regs->gpr[rd] = regs->ctr; + goto mtspr_out; + } + break; + case 0x378: /* orx */ + rs = (instr >> 21) & 0x1f; + rb = (instr >> 11) & 0x1f; + if (rs == rb) { /* mr */ + rd = (instr >> 16) & 0x1f; + regs->gpr[rd] = regs->gpr[rs]; + goto mtspr_out; + } + break; + case 0x3a6: /* mtspr */ + spr = (instr >> 11) & 0x3ff; + switch (spr) { + case 0x20: /* mtxer */ + regs->xer = (regs->gpr[rd] & 0xffffffffUL); + goto mtspr_out; + case 0x100: /* mtlr */ + regs->link = regs->gpr[rd]; + goto mtspr_out; + case 0x120: /* mtctr */ + regs->ctr = regs->gpr[rd]; +mtspr_out: + regs->nip += 4; + return 1; + } } } return 0; diff --git a/arch/powerpc/mm/hash_low_32.S b/arch/powerpc/mm/hash_low_32.S index bd68df5..ddceefc 100644 --- a/arch/powerpc/mm/hash_low_32.S +++ b/arch/powerpc/mm/hash_low_32.S @@ -283,6 +283,7 @@ Hash_msk = (((1 << Hash_bits) - 1) * 64) #define PTEG_SIZE 64 #define LG_PTEG_SIZE 6 #define LDPTEu lwzu +#define LDPTE lwz #define STPTE stw #define CMPPTE cmpw #define PTE_H 0x40 @@ -389,13 +390,30 @@ _GLOBAL(hash_page_patch_C) * and we know there is a definite (although small) speed * advantage to putting the PTE in the primary PTEG, we always * put the PTE in the primary PTEG. + * + * In addition, we skip any slot that is mapping kernel text in + * order to avoid a deadlock when not using BAT mappings if + * trying to hash in the kernel hash code itself after it has + * already taken the hash table lock. This works in conjunction + * with pre-faulting of the kernel text. + * + * If the hash table bucket is full of kernel text entries, we'll + * lockup here but that shouldn't happen */ - addis r4,r7,next_slot@ha + +1: addis r4,r7,next_slot@ha /* get next evict slot */ lwz r6,next_slot@l(r4) - addi r6,r6,PTE_SIZE + addi r6,r6,PTE_SIZE /* search for candidate */ andi. r6,r6,7*PTE_SIZE stw r6,next_slot@l(r4) add r4,r3,r6 + LDPTE r0,PTE_SIZE/2(r4) /* get PTE second word */ + clrrwi r0,r0,12 + lis r6,etext@h + ori r6,r6,etext@l /* get etext */ + tophys(r6,r6) + cmpl cr0,r0,r6 /* compare and try again */ + blt 1b #ifndef CONFIG_SMP /* Store PTE in PTEG */ diff --git a/arch/powerpc/mm/hash_low_64.S b/arch/powerpc/mm/hash_low_64.S index 9bc0a9c..e64ce3e 100644 --- a/arch/powerpc/mm/hash_low_64.S +++ b/arch/powerpc/mm/hash_low_64.S @@ -445,9 +445,12 @@ END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE) htab_insert_pte: /* real page number in r5, PTE RPN value + index */ - rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT + andis. r0,r31,_PAGE_4K_PFN@h + srdi r5,r31,PTE_RPN_SHIFT + bne- htab_special_pfn sldi r5,r5,PAGE_SHIFT-HW_PAGE_SHIFT add r5,r5,r25 +htab_special_pfn: sldi r5,r5,HW_PAGE_SHIFT /* Calculate primary group hash */ diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c index 6f1016a..79aedaf 100644 --- a/arch/powerpc/mm/hash_native_64.c +++ b/arch/powerpc/mm/hash_native_64.c @@ -505,7 +505,7 @@ static inline int tlb_batching_enabled(void) int enabled = 1; if (root) { - const char *model = get_property(root, "model", NULL); + const char *model = of_get_property(root, "model", NULL); if (model && !strcmp(model, "IBM,9076-N81")) enabled = 0; of_node_put(root); diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 3c7fe2c..4961846 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -100,6 +100,11 @@ unsigned int HPAGE_SHIFT; #ifdef CONFIG_PPC_64K_PAGES int mmu_ci_restrictions; #endif +#ifdef CONFIG_DEBUG_PAGEALLOC +static u8 *linear_map_hash_slots; +static unsigned long linear_map_hash_count; +static spinlock_t linear_map_hash_lock; +#endif /* CONFIG_DEBUG_PAGEALLOC */ /* There are definitions of page sizes arrays to be used when none * is provided by the firmware. @@ -152,11 +157,10 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend, for (vaddr = vstart, paddr = pstart; vaddr < vend; vaddr += step, paddr += step) { - unsigned long vpn, hash, hpteg; + unsigned long hash, hpteg; unsigned long vsid = get_kernel_vsid(vaddr); unsigned long va = (vsid << 28) | (vaddr & 0x0fffffff); - vpn = va >> shift; tmp_mode = mode; /* Make non-kernel text non-executable */ @@ -174,6 +178,10 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend, if (ret < 0) break; +#ifdef CONFIG_DEBUG_PAGEALLOC + if ((paddr >> PAGE_SHIFT) < linear_map_hash_count) + linear_map_hash_slots[paddr >> PAGE_SHIFT] = ret | 0x80; +#endif /* CONFIG_DEBUG_PAGEALLOC */ } return ret < 0 ? ret : 0; } @@ -281,6 +289,7 @@ static void __init htab_init_page_sizes(void) memcpy(mmu_psize_defs, mmu_psize_defaults_gp, sizeof(mmu_psize_defaults_gp)); found: +#ifndef CONFIG_DEBUG_PAGEALLOC /* * Pick a size for the linear mapping. Currently, we only support * 16M, 1M and 4K which is the default @@ -289,6 +298,7 @@ static void __init htab_init_page_sizes(void) mmu_linear_psize = MMU_PAGE_16M; else if (mmu_psize_defs[MMU_PAGE_1M].shift) mmu_linear_psize = MMU_PAGE_1M; +#endif /* CONFIG_DEBUG_PAGEALLOC */ #ifdef CONFIG_PPC_64K_PAGES /* @@ -303,12 +313,14 @@ static void __init htab_init_page_sizes(void) if (mmu_psize_defs[MMU_PAGE_64K].shift) { mmu_virtual_psize = MMU_PAGE_64K; mmu_vmalloc_psize = MMU_PAGE_64K; + if (mmu_linear_psize == MMU_PAGE_4K) + mmu_linear_psize = MMU_PAGE_64K; if (cpu_has_feature(CPU_FTR_CI_LARGE_PAGE)) mmu_io_psize = MMU_PAGE_64K; else mmu_ci_restrictions = 1; } -#endif +#endif /* CONFIG_PPC_64K_PAGES */ printk(KERN_DEBUG "Page orders: linear mapping = %d, " "virtual = %d, io = %d\n", @@ -476,6 +488,13 @@ void __init htab_initialize(void) mode_rw = _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX; +#ifdef CONFIG_DEBUG_PAGEALLOC + linear_map_hash_count = lmb_end_of_DRAM() >> PAGE_SHIFT; + linear_map_hash_slots = __va(lmb_alloc_base(linear_map_hash_count, + 1, lmb.rmo_size)); + memset(linear_map_hash_slots, 0, linear_map_hash_count); +#endif /* CONFIG_DEBUG_PAGEALLOC */ + /* On U3 based machines, we need to reserve the DART area and * _NOT_ map it to avoid cache paradoxes as it's remapped non * cacheable later on @@ -573,6 +592,27 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap) return pp; } +/* + * Demote a segment to using 4k pages. + * For now this makes the whole process use 4k pages. + */ +void demote_segment_4k(struct mm_struct *mm, unsigned long addr) +{ +#ifdef CONFIG_PPC_64K_PAGES + if (mm->context.user_psize == MMU_PAGE_4K) + return; + mm->context.user_psize = MMU_PAGE_4K; + mm->context.sllp = SLB_VSID_USER | mmu_psize_defs[MMU_PAGE_4K].sllp; + get_paca()->context = mm->context; + slb_flush_and_rebolt(); +#ifdef CONFIG_SPE_BASE + spu_flush_all_slbs(mm); +#endif +#endif +} + +EXPORT_SYMBOL_GPL(demote_segment_4k); + /* Result code is: * 0 - handled * 1 - normal page fault @@ -665,15 +705,19 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) #ifndef CONFIG_PPC_64K_PAGES rc = __hash_page_4K(ea, access, vsid, ptep, trap, local); #else + /* If _PAGE_4K_PFN is set, make sure this is a 4k segment */ + if (pte_val(*ptep) & _PAGE_4K_PFN) { + demote_segment_4k(mm, ea); + psize = MMU_PAGE_4K; + } + if (mmu_ci_restrictions) { /* If this PTE is non-cacheable, switch to 4k */ if (psize == MMU_PAGE_64K && (pte_val(*ptep) & _PAGE_NO_CACHE)) { if (user_region) { + demote_segment_4k(mm, ea); psize = MMU_PAGE_4K; - mm->context.user_psize = MMU_PAGE_4K; - mm->context.sllp = SLB_VSID_USER | - mmu_psize_defs[MMU_PAGE_4K].sllp; } else if (ea < VMALLOC_END) { /* * some driver did a non-cacheable mapping @@ -756,16 +800,8 @@ void hash_preload(struct mm_struct *mm, unsigned long ea, if (mmu_ci_restrictions) { /* If this PTE is non-cacheable, switch to 4k */ if (mm->context.user_psize == MMU_PAGE_64K && - (pte_val(*ptep) & _PAGE_NO_CACHE)) { - mm->context.user_psize = MMU_PAGE_4K; - mm->context.sllp = SLB_VSID_USER | - mmu_psize_defs[MMU_PAGE_4K].sllp; - get_paca()->context = mm->context; - slb_flush_and_rebolt(); -#ifdef CONFIG_SPE_BASE - spu_flush_all_slbs(mm); -#endif - } + (pte_val(*ptep) & _PAGE_NO_CACHE)) + demote_segment_4k(mm, ea); } if (mm->context.user_psize == MMU_PAGE_64K) __hash_page_64K(ea, access, vsid, ptep, trap, local); @@ -825,3 +861,62 @@ void low_hash_fault(struct pt_regs *regs, unsigned long address) } bad_page_fault(regs, address, SIGBUS); } + +#ifdef CONFIG_DEBUG_PAGEALLOC +static void kernel_map_linear_page(unsigned long vaddr, unsigned long lmi) +{ + unsigned long hash, hpteg, vsid = get_kernel_vsid(vaddr); + unsigned long va = (vsid << 28) | (vaddr & 0x0fffffff); + unsigned long mode = _PAGE_ACCESSED | _PAGE_DIRTY | + _PAGE_COHERENT | PP_RWXX | HPTE_R_N; + int ret; + + hash = hpt_hash(va, PAGE_SHIFT); + hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP); + + ret = ppc_md.hpte_insert(hpteg, va, __pa(vaddr), + mode, HPTE_V_BOLTED, mmu_linear_psize); + BUG_ON (ret < 0); + spin_lock(&linear_map_hash_lock); + BUG_ON(linear_map_hash_slots[lmi] & 0x80); + linear_map_hash_slots[lmi] = ret | 0x80; + spin_unlock(&linear_map_hash_lock); +} + +static void kernel_unmap_linear_page(unsigned long vaddr, unsigned long lmi) +{ + unsigned long hash, hidx, slot, vsid = get_kernel_vsid(vaddr); + unsigned long va = (vsid << 28) | (vaddr & 0x0fffffff); + + hash = hpt_hash(va, PAGE_SHIFT); + spin_lock(&linear_map_hash_lock); + BUG_ON(!(linear_map_hash_slots[lmi] & 0x80)); + hidx = linear_map_hash_slots[lmi] & 0x7f; + linear_map_hash_slots[lmi] = 0; + spin_unlock(&linear_map_hash_lock); + if (hidx & _PTEIDX_SECONDARY) + hash = ~hash; + slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; + slot += hidx & _PTEIDX_GROUP_IX; + ppc_md.hpte_invalidate(slot, va, mmu_linear_psize, 0); +} + +void kernel_map_pages(struct page *page, int numpages, int enable) +{ + unsigned long flags, vaddr, lmi; + int i; + + local_irq_save(flags); + for (i = 0; i < numpages; i++, page++) { + vaddr = (unsigned long)page_address(page); + lmi = __pa(vaddr) >> PAGE_SHIFT; + if (lmi >= linear_map_hash_count) + continue; + if (enable) + kernel_map_linear_page(vaddr, lmi); + else + kernel_unmap_linear_page(vaddr, lmi); + } + local_irq_restore(flags); +} +#endif /* CONFIG_DEBUG_PAGEALLOC */ diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index f6ffaaa..8508f97 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c @@ -316,12 +316,11 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, { if (pte_present(*ptep)) { /* We open-code pte_clear because we need to pass the right - * argument to hpte_update (huge / !huge) + * argument to hpte_need_flush (huge / !huge). Might not be + * necessary anymore if we make hpte_need_flush() get the + * page size from the slices */ - unsigned long old = pte_update(ptep, ~0UL); - if (old & _PAGE_HASHPTE) - hpte_update(mm, addr & HPAGE_MASK, ptep, old, 1); - flush_tlb_pending(); + pte_update(mm, addr & HPAGE_MASK, ptep, ~0UL, 1); } *ptep = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS); } @@ -329,12 +328,7 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { - unsigned long old = pte_update(ptep, ~0UL); - - if (old & _PAGE_HASHPTE) - hpte_update(mm, addr & HPAGE_MASK, ptep, old, 1); - *ptep = __pte(0); - + unsigned long old = pte_update(mm, addr, ptep, ~0UL, 1); return __pte(old); } diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c index 0e53ca8..5fce6cc 100644 --- a/arch/powerpc/mm/init_32.c +++ b/arch/powerpc/mm/init_32.c @@ -115,6 +115,10 @@ void MMU_setup(void) if (strstr(cmd_line, "noltlbs")) { __map_without_ltlbs = 1; } +#ifdef CONFIG_DEBUG_PAGEALLOC + __map_without_bats = 1; + __map_without_ltlbs = 1; +#endif } /* diff --git a/arch/powerpc/mm/lmb.c b/arch/powerpc/mm/lmb.c index 716a290..e3a1e8d 100644 --- a/arch/powerpc/mm/lmb.c +++ b/arch/powerpc/mm/lmb.c @@ -146,6 +146,10 @@ static long __init lmb_add_region(struct lmb_region *rgn, unsigned long base, unsigned long rgnbase = rgn->region[i].base; unsigned long rgnsize = rgn->region[i].size; + if ((rgnbase == base) && (rgnsize == size)) + /* Already have this region, so we're done */ + return 0; + adjacent = lmb_addrs_adjacent(base,size,rgnbase,rgnsize); if ( adjacent > 0 ) { rgn->region[i].base -= size; diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 52f397c1..c4bcd75 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -58,9 +58,6 @@ int init_bootmem_done; int mem_init_done; unsigned long memory_limit; -extern void hash_preload(struct mm_struct *mm, unsigned long ea, - unsigned long access, unsigned long trap); - int page_is_ram(unsigned long pfn) { unsigned long paddr = (pfn << PAGE_SHIFT); diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h index bea2d21..9c4538b 100644 --- a/arch/powerpc/mm/mmu_decl.h +++ b/arch/powerpc/mm/mmu_decl.h @@ -19,9 +19,14 @@ * 2 of the License, or (at your option) any later version. * */ +#include <linux/mm.h> #include <asm/tlbflush.h> #include <asm/mmu.h> +extern void hash_preload(struct mm_struct *mm, unsigned long ea, + unsigned long access, unsigned long trap); + + #ifdef CONFIG_PPC32 extern void mapin_ram(void); extern int map_page(unsigned long va, phys_addr_t pa, int flags); diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index e86c37c..b3a592b 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -74,7 +74,7 @@ static struct device_node * __cpuinit find_cpu_node(unsigned int cpu) while ((cpu_node = of_find_node_by_type(cpu_node, "cpu")) != NULL) { /* Try interrupt server first */ - interrupt_server = get_property(cpu_node, + interrupt_server = of_get_property(cpu_node, "ibm,ppc-interrupt-server#s", &len); len = len / sizeof(u32); @@ -85,7 +85,7 @@ static struct device_node * __cpuinit find_cpu_node(unsigned int cpu) return cpu_node; } } else { - reg = get_property(cpu_node, "reg", &len); + reg = of_get_property(cpu_node, "reg", &len); if (reg && (len > 0) && (reg[0] == hw_cpuid)) return cpu_node; } @@ -97,7 +97,7 @@ static struct device_node * __cpuinit find_cpu_node(unsigned int cpu) /* must hold reference to node during call */ static const int *of_get_associativity(struct device_node *dev) { - return get_property(dev, "ibm,associativity", NULL); + return of_get_property(dev, "ibm,associativity", NULL); } /* Returns nid in the range [0..MAX_NUMNODES-1], or -1 if no useful numa @@ -179,7 +179,7 @@ static int __init find_min_common_depth(void) * configuration (should be all 0's) and the second is for a normal * NUMA configuration. */ - ref_points = get_property(rtas_root, + ref_points = of_get_property(rtas_root, "ibm,associativity-reference-points", &len); if ((len >= 1) && ref_points) { @@ -201,8 +201,8 @@ static void __init get_n_mem_cells(int *n_addr_cells, int *n_size_cells) if (!memory) panic("numa.c: No memory nodes found!"); - *n_addr_cells = prom_n_addr_cells(memory); - *n_size_cells = prom_n_size_cells(memory); + *n_addr_cells = of_n_addr_cells(memory); + *n_size_cells = of_n_size_cells(memory); of_node_put(memory); } @@ -308,9 +308,9 @@ static void __init parse_drconf_memory(struct device_node *memory) int nid, default_nid = 0; unsigned int start, ai, flags; - lm = get_property(memory, "ibm,lmb-size", &ls); - dm = get_property(memory, "ibm,dynamic-memory", &ld); - aa = get_property(memory, "ibm,associativity-lookup-arrays", &la); + lm = of_get_property(memory, "ibm,lmb-size", &ls); + dm = of_get_property(memory, "ibm,dynamic-memory", &ld); + aa = of_get_property(memory, "ibm,associativity-lookup-arrays", &la); if (!lm || !dm || !aa || ls < sizeof(unsigned int) || ld < sizeof(unsigned int) || la < 2 * sizeof(unsigned int)) @@ -404,10 +404,10 @@ static int __init parse_numa_properties(void) const unsigned int *memcell_buf; unsigned int len; - memcell_buf = get_property(memory, + memcell_buf = of_get_property(memory, "linux,usable-memory", &len); if (!memcell_buf || len <= 0) - memcell_buf = get_property(memory, "reg", &len); + memcell_buf = of_get_property(memory, "reg", &len); if (!memcell_buf || len <= 0) continue; @@ -725,7 +725,7 @@ int hot_add_scn_to_nid(unsigned long scn_addr) const unsigned int *memcell_buf; unsigned int len; - memcell_buf = get_property(memory, "reg", &len); + memcell_buf = of_get_property(memory, "reg", &len); if (!memcell_buf || len <= 0) continue; diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index c284bda..bca5603 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c @@ -183,8 +183,8 @@ __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags) * mem_init() sets high_memory so only do the check after that. */ if (mem_init_done && (p < virt_to_phys(high_memory))) { - printk("__ioremap(): phys addr "PHYS_FMT" is RAM lr %p\n", p, - __builtin_return_address(0)); + printk("__ioremap(): phys addr 0x%llx is RAM lr %p\n", + (unsigned long long)p, __builtin_return_address(0)); return NULL; } @@ -266,9 +266,12 @@ int map_page(unsigned long va, phys_addr_t pa, int flags) pg = pte_alloc_kernel(pd, va); if (pg != 0) { err = 0; - set_pte_at(&init_mm, va, pg, pfn_pte(pa >> PAGE_SHIFT, __pgprot(flags))); - if (mem_init_done) - flush_HPTE(0, va, pmd_val(*pd)); + /* The PTE should never be already set nor present in the + * hash table + */ + BUG_ON(pte_val(*pg) & (_PAGE_PRESENT | _PAGE_HASHPTE)); + set_pte_at(&init_mm, va, pg, pfn_pte(pa >> PAGE_SHIFT, + __pgprot(flags))); } return err; } @@ -279,16 +282,19 @@ int map_page(unsigned long va, phys_addr_t pa, int flags) void __init mapin_ram(void) { unsigned long v, p, s, f; + int ktext; s = mmu_mapin_ram(); v = KERNELBASE + s; p = PPC_MEMSTART + s; for (; s < total_lowmem; s += PAGE_SIZE) { - if ((char *) v >= _stext && (char *) v < etext) - f = _PAGE_RAM_TEXT; - else - f = _PAGE_RAM; + ktext = ((char *) v >= _stext && (char *) v < etext); + f = ktext ?_PAGE_RAM_TEXT : _PAGE_RAM; map_page(v, p, f); +#ifdef CONFIG_PPC_STD_MMU_32 + if (ktext) + hash_preload(&init_mm, v, 0, 0x300); +#endif v += PAGE_SIZE; p += PAGE_SIZE; } @@ -445,3 +451,55 @@ exit: return ret; } +#ifdef CONFIG_DEBUG_PAGEALLOC + +static int __change_page_attr(struct page *page, pgprot_t prot) +{ + pte_t *kpte; + pmd_t *kpmd; + unsigned long address; + + BUG_ON(PageHighMem(page)); + address = (unsigned long)page_address(page); + + if (v_mapped_by_bats(address) || v_mapped_by_tlbcam(address)) + return 0; + if (!get_pteptr(&init_mm, address, &kpte, &kpmd)) + return -EINVAL; + set_pte_at(&init_mm, address, kpte, mk_pte(page, prot)); + wmb(); + flush_HPTE(0, address, pmd_val(*kpmd)); + pte_unmap(kpte); + + return 0; +} + +/* + * Change the page attributes of an page in the linear mapping. + * + * THIS CONFLICTS WITH BAT MAPPINGS, DEBUG USE ONLY + */ +static int change_page_attr(struct page *page, int numpages, pgprot_t prot) +{ + int i, err = 0; + unsigned long flags; + + local_irq_save(flags); + for (i = 0; i < numpages; i++, page++) { + err = __change_page_attr(page, prot); + if (err) + break; + } + local_irq_restore(flags); + return err; +} + + +void kernel_map_pages(struct page *page, int numpages, int enable) +{ + if (PageHighMem(page)) + return; + + change_page_attr(page, numpages, enable ? PAGE_KERNEL : __pgprot(0)); +} +#endif /* CONFIG_DEBUG_PAGEALLOC */ diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c index 7cceb2c..0506667 100644 --- a/arch/powerpc/mm/ppc_mmu_32.c +++ b/arch/powerpc/mm/ppc_mmu_32.c @@ -85,8 +85,10 @@ unsigned long __init mmu_mapin_ram(void) unsigned long max_size = (256<<20); unsigned long align; - if (__map_without_bats) + if (__map_without_bats) { + printk(KERN_DEBUG "RAM mapped without BATs\n"); return 0; + } /* Set up BAT2 and if necessary BAT3 to cover RAM. */ diff --git a/arch/powerpc/mm/tlb_64.c b/arch/powerpc/mm/tlb_64.c index b58baa6..fd8d08c 100644 --- a/arch/powerpc/mm/tlb_64.c +++ b/arch/powerpc/mm/tlb_64.c @@ -120,17 +120,20 @@ void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf) } /* - * Update the MMU hash table to correspond with a change to - * a Linux PTE. If wrprot is true, it is permissible to - * change the existing HPTE to read-only rather than removing it - * (if we remove it we should clear the _PTE_HPTEFLAGS bits). + * A linux PTE was changed and the corresponding hash table entry + * neesd to be flushed. This function will either perform the flush + * immediately or will batch it up if the current CPU has an active + * batch on it. + * + * Must be called from within some kind of spinlock/non-preempt region... */ -void hpte_update(struct mm_struct *mm, unsigned long addr, - pte_t *ptep, unsigned long pte, int huge) +void hpte_need_flush(struct mm_struct *mm, unsigned long addr, + pte_t *ptep, unsigned long pte, int huge) { struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); - unsigned long vsid; + unsigned long vsid, vaddr; unsigned int psize; + real_pte_t rpte; int i; i = batch->index; @@ -151,6 +154,26 @@ void hpte_update(struct mm_struct *mm, unsigned long addr, } else psize = pte_pagesize_index(pte); + /* Build full vaddr */ + if (!is_kernel_addr(addr)) { + vsid = get_vsid(mm->context.id, addr); + WARN_ON(vsid == 0); + } else + vsid = get_kernel_vsid(addr); + vaddr = (vsid << 28 ) | (addr & 0x0fffffff); + rpte = __real_pte(__pte(pte), ptep); + + /* + * Check if we have an active batch on this CPU. If not, just + * flush now and return. For now, we don global invalidates + * in that case, might be worth testing the mm cpu mask though + * and decide to use local invalidates instead... + */ + if (!batch->active) { + flush_hash_page(vaddr, rpte, psize, 0); + return; + } + /* * This can happen when we are in the middle of a TLB batch and * we encounter memory pressure (eg copy_page_range when it tries @@ -162,47 +185,42 @@ void hpte_update(struct mm_struct *mm, unsigned long addr, * batch */ if (i != 0 && (mm != batch->mm || batch->psize != psize)) { - flush_tlb_pending(); + __flush_tlb_pending(batch); i = 0; } if (i == 0) { batch->mm = mm; batch->psize = psize; } - if (!is_kernel_addr(addr)) { - vsid = get_vsid(mm->context.id, addr); - WARN_ON(vsid == 0); - } else - vsid = get_kernel_vsid(addr); - batch->vaddr[i] = (vsid << 28 ) | (addr & 0x0fffffff); - batch->pte[i] = __real_pte(__pte(pte), ptep); + batch->pte[i] = rpte; + batch->vaddr[i] = vaddr; batch->index = ++i; if (i >= PPC64_TLB_BATCH_NR) - flush_tlb_pending(); + __flush_tlb_pending(batch); } +/* + * This function is called when terminating an mmu batch or when a batch + * is full. It will perform the flush of all the entries currently stored + * in a batch. + * + * Must be called from within some kind of spinlock/non-preempt region... + */ void __flush_tlb_pending(struct ppc64_tlb_batch *batch) { - int i; - int cpu; cpumask_t tmp; - int local = 0; + int i, local = 0; - BUG_ON(in_interrupt()); - - cpu = get_cpu(); i = batch->index; - tmp = cpumask_of_cpu(cpu); + tmp = cpumask_of_cpu(smp_processor_id()); if (cpus_equal(batch->mm->cpu_vm_mask, tmp)) local = 1; - if (i == 1) flush_hash_page(batch->vaddr[0], batch->pte[0], batch->psize, local); else flush_hash_range(i, local); batch->index = 0; - put_cpu(); } void pte_free_finish(void) diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile index 4ccef2d..4b5f952 100644 --- a/arch/powerpc/oprofile/Makefile +++ b/arch/powerpc/oprofile/Makefile @@ -12,6 +12,6 @@ DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \ oprofile-y := $(DRIVER_OBJS) common.o backtrace.o oprofile-$(CONFIG_PPC_CELL_NATIVE) += op_model_cell.o -oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o +oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o op_model_pa6t.o oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o oprofile-$(CONFIG_6xx) += op_model_7450.o diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c index fbd62ea..1a7ef7e 100644 --- a/arch/powerpc/oprofile/common.c +++ b/arch/powerpc/oprofile/common.c @@ -160,6 +160,9 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) case PPC_OPROFILE_POWER4: model = &op_model_power4; break; + case PPC_OPROFILE_PA6T: + model = &op_model_pa6t; + break; #endif #ifdef CONFIG_6xx case PPC_OPROFILE_G4: diff --git a/arch/powerpc/oprofile/op_model_cell.c b/arch/powerpc/oprofile/op_model_cell.c index e08e1d7..626b29f 100644 --- a/arch/powerpc/oprofile/op_model_cell.c +++ b/arch/powerpc/oprofile/op_model_cell.c @@ -37,6 +37,7 @@ #include <asm/system.h> #include "../platforms/cell/interrupt.h" +#include "../platforms/cell/cbe_regs.h" #define PPU_CYCLES_EVENT_NUM 1 /* event number for CYCLES */ #define PPU_CYCLES_GRP_NUM 1 /* special group number for identifying @@ -130,7 +131,7 @@ static int pm_rtas_token; static u32 reset_value[NR_PHYS_CTRS]; static int num_counters; static int oprofile_running; -static spinlock_t virt_cntr_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(virt_cntr_lock); static u32 ctr_enabled; diff --git a/arch/powerpc/oprofile/op_model_pa6t.c b/arch/powerpc/oprofile/op_model_pa6t.c new file mode 100644 index 0000000..e8a56b0 --- /dev/null +++ b/arch/powerpc/oprofile/op_model_pa6t.c @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2006-2007 PA Semi, Inc + * + * Author: Shashi Rao, PA Semi + * + * Maintained by: Olof Johansson <olof@lixom.net> + * + * Based on arch/powerpc/oprofile/op_model_power4.c + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/oprofile.h> +#include <linux/init.h> +#include <linux/smp.h> +#include <linux/percpu.h> +#include <asm/processor.h> +#include <asm/cputable.h> +#include <asm/oprofile_impl.h> +#include <asm/reg.h> + +static unsigned char oprofile_running; + +/* mmcr values are set in pa6t_reg_setup, used in pa6t_cpu_setup */ +static u64 mmcr0_val; +static u64 mmcr1_val; + +/* inited in pa6t_reg_setup */ +static u64 reset_value[OP_MAX_COUNTER]; + +static inline u64 ctr_read(unsigned int i) +{ + switch (i) { + case 0: + return mfspr(SPRN_PA6T_PMC0); + case 1: + return mfspr(SPRN_PA6T_PMC1); + case 2: + return mfspr(SPRN_PA6T_PMC2); + case 3: + return mfspr(SPRN_PA6T_PMC3); + case 4: + return mfspr(SPRN_PA6T_PMC4); + case 5: + return mfspr(SPRN_PA6T_PMC5); + default: + printk(KERN_ERR "ctr_read called with bad arg %u\n", i); + return 0; + } +} + +static inline void ctr_write(unsigned int i, u64 val) +{ + switch (i) { + case 0: + mtspr(SPRN_PA6T_PMC0, val); + break; + case 1: + mtspr(SPRN_PA6T_PMC1, val); + break; + case 2: + mtspr(SPRN_PA6T_PMC2, val); + break; + case 3: + mtspr(SPRN_PA6T_PMC3, val); + break; + case 4: + mtspr(SPRN_PA6T_PMC4, val); + break; + case 5: + mtspr(SPRN_PA6T_PMC5, val); + break; + default: + printk(KERN_ERR "ctr_write called with bad arg %u\n", i); + break; + } +} + + +/* precompute the values to stuff in the hardware registers */ +static void pa6t_reg_setup(struct op_counter_config *ctr, + struct op_system_config *sys, + int num_ctrs) +{ + int pmc; + + /* + * adjust the mmcr0.en[0-5] and mmcr0.inten[0-5] values obtained from the + * event_mappings file by turning off the counters that the user doesn't + * care about + * + * setup user and kernel profiling + */ + for (pmc = 0; pmc < cur_cpu_spec->num_pmcs; pmc++) + if (!ctr[pmc].enabled) { + sys->mmcr0 &= ~(0x1UL << pmc); + sys->mmcr0 &= ~(0x1UL << (pmc+12)); + pr_debug("turned off counter %u\n", pmc); + } + + if (sys->enable_kernel) + sys->mmcr0 |= PA6T_MMCR0_SUPEN | PA6T_MMCR0_HYPEN; + else + sys->mmcr0 &= ~(PA6T_MMCR0_SUPEN | PA6T_MMCR0_HYPEN); + + if (sys->enable_user) + sys->mmcr0 |= PA6T_MMCR0_PREN; + else + sys->mmcr0 &= ~PA6T_MMCR0_PREN; + + /* + * The performance counter event settings are given in the mmcr0 and + * mmcr1 values passed from the user in the op_system_config + * structure (sys variable). + */ + mmcr0_val = sys->mmcr0; + mmcr1_val = sys->mmcr1; + pr_debug("mmcr0_val inited to %016lx\n", sys->mmcr0); + pr_debug("mmcr1_val inited to %016lx\n", sys->mmcr1); + + for (pmc = 0; pmc < cur_cpu_spec->num_pmcs; pmc++) { + /* counters are 40 bit. Move to cputable at some point? */ + reset_value[pmc] = (0x1UL << 39) - ctr[pmc].count; + pr_debug("reset_value for pmc%u inited to 0x%lx\n", + pmc, reset_value[pmc]); + } +} + +/* configure registers on this cpu */ +static void pa6t_cpu_setup(struct op_counter_config *ctr) +{ + u64 mmcr0 = mmcr0_val; + u64 mmcr1 = mmcr1_val; + + /* Default is all PMCs off */ + mmcr0 &= ~(0x3FUL); + mtspr(SPRN_PA6T_MMCR0, mmcr0); + + /* program selected programmable events in */ + mtspr(SPRN_PA6T_MMCR1, mmcr1); + + pr_debug("setup on cpu %d, mmcr0 %016lx\n", smp_processor_id(), + mfspr(SPRN_PA6T_MMCR0)); + pr_debug("setup on cpu %d, mmcr1 %016lx\n", smp_processor_id(), + mfspr(SPRN_PA6T_MMCR1)); +} + +static void pa6t_start(struct op_counter_config *ctr) +{ + int i; + + /* Hold off event counting until rfid */ + u64 mmcr0 = mmcr0_val | PA6T_MMCR0_HANDDIS; + + for (i = 0; i < cur_cpu_spec->num_pmcs; i++) + if (ctr[i].enabled) + ctr_write(i, reset_value[i]); + else + ctr_write(i, 0UL); + + mtspr(SPRN_PA6T_MMCR0, mmcr0); + + oprofile_running = 1; + + pr_debug("start on cpu %d, mmcr0 %lx\n", smp_processor_id(), mmcr0); +} + +static void pa6t_stop(void) +{ + u64 mmcr0; + + /* freeze counters */ + mmcr0 = mfspr(SPRN_PA6T_MMCR0); + mmcr0 |= PA6T_MMCR0_FCM0; + mtspr(SPRN_PA6T_MMCR0, mmcr0); + + oprofile_running = 0; + + pr_debug("stop on cpu %d, mmcr0 %lx\n", smp_processor_id(), mmcr0); +} + +/* handle the perfmon overflow vector */ +static void pa6t_handle_interrupt(struct pt_regs *regs, + struct op_counter_config *ctr) +{ + unsigned long pc = mfspr(SPRN_PA6T_SIAR); + int is_kernel = is_kernel_addr(pc); + u64 val; + int i; + u64 mmcr0; + + /* disable perfmon counting until rfid */ + mmcr0 = mfspr(SPRN_PA6T_MMCR0); + mtspr(SPRN_PA6T_MMCR0, mmcr0 | PA6T_MMCR0_HANDDIS); + + /* Record samples. We've got one global bit for whether a sample + * was taken, so add it for any counter that triggered overflow. + */ + for (i = 0; i < cur_cpu_spec->num_pmcs; i++) { + val = ctr_read(i); + if (val & (0x1UL << 39)) { /* Overflow bit set */ + if (oprofile_running && ctr[i].enabled) { + if (mmcr0 & PA6T_MMCR0_SIARLOG) + oprofile_add_ext_sample(pc, regs, i, is_kernel); + ctr_write(i, reset_value[i]); + } else { + ctr_write(i, 0UL); + } + } + } + + /* Restore mmcr0 to a good known value since the PMI changes it */ + mmcr0 = mmcr0_val | PA6T_MMCR0_HANDDIS; + mtspr(SPRN_PA6T_MMCR0, mmcr0); +} + +struct op_powerpc_model op_model_pa6t = { + .reg_setup = pa6t_reg_setup, + .cpu_setup = pa6t_cpu_setup, + .start = pa6t_start, + .stop = pa6t_stop, + .handle_interrupt = pa6t_handle_interrupt, +}; diff --git a/arch/powerpc/platforms/4xx/Kconfig b/arch/powerpc/platforms/4xx/Kconfig index 2f2a13e..ded357c 100644 --- a/arch/powerpc/platforms/4xx/Kconfig +++ b/arch/powerpc/platforms/4xx/Kconfig @@ -3,278 +3,206 @@ config 4xx depends on 40x || 44x default y -config WANT_EARLY_SERIAL +config BOOKE bool - select SERIAL_8250 - default n - -menu "AMCC 4xx options" - depends on 4xx - -choice - prompt "Machine Type" - depends on 40x - default WALNUT - -config BUBINGA - bool "Bubinga" - select WANT_EARLY_SERIAL - help - This option enables support for the IBM 405EP evaluation board. - -config CPCI405 - bool "CPCI405" - help - This option enables support for the CPCI405 board. - -config EP405 - bool "EP405/EP405PC" - help - This option enables support for the EP405/EP405PC boards. - -config REDWOOD_5 - bool "Redwood-5" - help - This option enables support for the IBM STB04 evaluation board. - -config REDWOOD_6 - bool "Redwood-6" - help - This option enables support for the IBM STBx25xx evaluation board. - -config SYCAMORE - bool "Sycamore" - help - This option enables support for the IBM PPC405GPr evaluation board. - -config WALNUT - bool "Walnut" - help - This option enables support for the IBM PPC405GP evaluation board. - -config XILINX_ML300 - bool "Xilinx-ML300" - help - This option enables support for the Xilinx ML300 evaluation board. - -endchoice - -choice - prompt "Machine Type" depends on 44x - default EBONY - -config BAMBOO - bool "Bamboo" - select WANT_EARLY_SERIAL - help - This option enables support for the IBM PPC440EP evaluation board. - -config EBONY - bool "Ebony" - select WANT_EARLY_SERIAL - help - This option enables support for the IBM PPC440GP evaluation board. - -config LUAN - bool "Luan" - select WANT_EARLY_SERIAL - help - This option enables support for the IBM PPC440SP evaluation board. - -config OCOTEA - bool "Ocotea" - select WANT_EARLY_SERIAL - help - This option enables support for the IBM PPC440GX evaluation board. + default y -endchoice +menu "AMCC 40x options" + depends on 40x -config EP405PC - bool "EP405PC Support" - depends on EP405 +#config BUBINGA +# bool "Bubinga" +# depends on 40x +# default n +# select 405EP +# help +# This option enables support for the IBM 405EP evaluation board. + +#config CPCI405 +# bool "CPCI405" +# depends on 40x +# default n +# select 405GP +# help +# This option enables support for the CPCI405 board. + +#config EP405 +# bool "EP405/EP405PC" +# depends on 40x +# default n +# select 405GP +# help +# This option enables support for the EP405/EP405PC boards. + +#config EP405PC +# bool "EP405PC Support" +# depends on EP405 +# default y +# help +# This option enables support for the extra features of the EP405PC board. + +#config REDWOOD_5 +# bool "Redwood-5" +# depends on 40x +# default n +# select STB03xxx +# help +# This option enables support for the IBM STB04 evaluation board. + +#config REDWOOD_6 +# bool "Redwood-6" +# depends on 40x +# default n +# select STB03xxx +# help +# This option enables support for the IBM STBx25xx evaluation board. + +#config SYCAMORE +# bool "Sycamore" +# depends on 40x +# default n +# select 405GPR +# help +# This option enables support for the IBM PPC405GPr evaluation board. + +#config WALNUT +# bool "Walnut" +# depends on 40x +# default y +# select 405GP +# help +# This option enables support for the IBM PPC405GP evaluation board. + +#config XILINX_ML300 +# bool "Xilinx-ML300" +# depends on 40x +# default y +# select VIRTEX_II_PRO +# help +# This option enables support for the Xilinx ML300 evaluation board. +endmenu -# It's often necessary to know the specific 4xx processor type. -# Fortunately, it is impled (so far) from the board type, so we -# don't need to ask more redundant questions. +# 40x specific CPU modules, selected based on the board above. config NP405H bool - depends on ASH - default y + #depends on ASH -config 440EP +# OAK doesn't exist but wanted to keep this around for any future 403GCX boards +config 403GCX bool - depends on BAMBOO - select PPC_FPU - default y + #depends on OAK + select IBM405_ERR51 -config 440GP +config 405GP bool - depends on EBONY - default y + select IBM405_ERR77 + select IBM405_ERR51 -config 440GX +config 405EP bool - depends on OCOTEA - default y -config 440SP +config 405GPR bool - depends on LUAN - default y -config 440 +config VIRTEX_II_PRO bool - depends on 440GP || 440SP || 440EP - default y + select IBM405_ERR77 + select IBM405_ERR51 -config 440A +config STB03xxx bool - depends on 440GX - default y + select IBM405_ERR77 + select IBM405_ERR51 -config IBM440EP_ERR42 - bool - depends on 440EP - default y +# 40x errata/workaround config symbols, selected by the CPU models above # All 405-based cores up until the 405GPR and 405EP have this errata. config IBM405_ERR77 bool - depends on 40x && !403GCX && !405GPR && !405EP - default y # All 40x-based cores, up until the 405GPR and 405EP have this errata. config IBM405_ERR51 bool - depends on 40x && !405GPR && !405EP - default y -config BOOKE - bool +menu "AMCC 44x options" depends on 44x - default y - -config IBM_OCP - bool - depends on ASH || BAMBOO || BUBINGA || CPCI405 || EBONY || EP405 || LUAN || OCOTEA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT - default y -config XILINX_OCP - bool - depends on XILINX_ML300 - default y +#config BAMBOO +# bool "Bamboo" +# depends on 44x +# default n +# select 440EP +# help +# This option enables support for the IBM PPC440EP evaluation board. -config IBM_EMAC4 - bool - depends on 440GX || 440SP - default y - -config BIOS_FIXUP - bool - depends on BUBINGA || EP405 || SYCAMORE || WALNUT - default y - -# OAK doesn't exist but wanted to keep this around for any future 403GCX boards -config 403GCX - bool - depends on OAK - default y - -config 405EP - bool - depends on BUBINGA - default y - -config 405GP - bool - depends on CPCI405 || EP405 || WALNUT - default y - -config 405GPR - bool - depends on SYCAMORE +config EBONY + bool "Ebony" + depends on 44x default y + select 440GP + help + This option enables support for the IBM PPC440GP evaluation board. -config VIRTEX_II_PRO - bool - depends on XILINX_ML300 - default y +#config LUAN +# bool "Luan" +# depends on 44x +# default n +# select 440SP +# help +# This option enables support for the IBM PPC440SP evaluation board. + +#config OCOTEA +# bool "Ocotea" +# depends on 44x +# default n +# select 440GX +# help +# This option enables support for the IBM PPC440GX evaluation board. -config STB03xxx - bool - depends on REDWOOD_5 || REDWOOD_6 - default y +endmenu -config EMBEDDEDBOOT +# 44x specific CPU modules, selected based on the board above. +config 440EP bool - depends on EP405 || XILINX_ML300 - default y + select PPC_FPU + select IBM440EP_ERR42 -config IBM_OPENBIOS +config 440GP bool - depends on ASH || BUBINGA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT - default y + select IBM_NEW_EMAC_ZMII -config PPC4xx_DMA - bool "PPC4xx DMA controller support" - depends on 4xx - -config PPC4xx_EDMA +config 440GX bool - depends on !STB03xxx && PPC4xx_DMA - default y -config PPC_GEN550 +config 440SP bool - depends on 4xx - default y - -choice - prompt "TTYS0 device and default console" - depends on 40x - default UART0_TTYS0 - -config UART0_TTYS0 - bool "UART0" -config UART0_TTYS1 - bool "UART1" - -endchoice - -config SERIAL_SICC - bool "SICC Serial port support" - depends on STB03xxx - -config UART1_DFLT_CONSOLE +config 440A bool - depends on SERIAL_SICC && UART0_TTYS1 + depends on 440GX default y -config SERIAL_SICC_CONSOLE +# 44x errata/workaround config symbols, selected by the CPU models above +config IBM440EP_ERR42 bool - depends on SERIAL_SICC && UART0_TTYS1 - default y -endmenu +#config XILINX_OCP +# bool +# depends on XILINX_ML300 +# default y -menu "IBM 40x options" - depends on 40x - -config SERIAL_SICC - bool "SICC Serial port" - depends on STB03xxx - -config UART1_DFLT_CONSOLE - bool - depends on SERIAL_SICC && UART0_TTYS1 - default y +#config BIOS_FIXUP +# bool +# depends on BUBINGA || EP405 || SYCAMORE || WALNUT +# default y -config SERIAL_SICC_CONSOLE - bool - depends on SERIAL_SICC && UART0_TTYS1 - default y +#config PPC4xx_DMA +# bool "PPC4xx DMA controller support" +# depends on 4xx -endmenu +#config PPC4xx_EDMA +# bool +# depends on !STB03xxx && PPC4xx_DMA +# default y diff --git a/arch/powerpc/platforms/52xx/Kconfig b/arch/powerpc/platforms/52xx/Kconfig new file mode 100644 index 0000000..bc4aa4a --- /dev/null +++ b/arch/powerpc/platforms/52xx/Kconfig @@ -0,0 +1,35 @@ +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 + + diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c index 8de0341..a6bba97 100644 --- a/arch/powerpc/platforms/52xx/efika.c +++ b/arch/powerpc/platforms/52xx/efika.c @@ -112,7 +112,7 @@ void __init efika_pcisetup(void) return; } - bus_range = get_property(pcictrl, "bus-range", &len); + bus_range = of_get_property(pcictrl, "bus-range", &len); if (bus_range == NULL || len < 2 * sizeof(int)) { printk(KERN_WARNING EFIKA_PLATFORM_NAME ": Can't get bus-range for %s\n", pcictrl->full_name); @@ -158,18 +158,17 @@ void __init efika_pcisetup(void) static void efika_show_cpuinfo(struct seq_file *m) { struct device_node *root; - const char *revision = NULL; - const char *codegendescription = NULL; - const char *codegenvendor = NULL; + const char *revision; + const char *codegendescription; + const char *codegenvendor; root = of_find_node_by_path("/"); if (!root) return; - revision = get_property(root, "revision", NULL); - codegendescription = - get_property(root, "CODEGEN,description", NULL); - codegenvendor = get_property(root, "CODEGEN,vendor", NULL); + revision = of_get_property(root, "revision", NULL); + codegendescription = of_get_property(root, "CODEGEN,description", NULL); + codegenvendor = of_get_property(root, "CODEGEN,vendor", NULL); if (codegendescription) seq_printf(m, "machine\t\t: %s\n", codegendescription); diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c index cc3b40d..8e2646a 100644 --- a/arch/powerpc/platforms/52xx/lite5200.c +++ b/arch/powerpc/platforms/52xx/lite5200.c @@ -94,8 +94,8 @@ static void __init lite5200_setup_arch(void) np = of_find_node_by_type(NULL, "cpu"); if (np) { - unsigned int *fp = - (int *)get_property(np, "clock-frequency", NULL); + const unsigned int *fp = + of_get_property(np, "clock-frequency", NULL); if (fp != 0) loops_per_jiffy = *fp / HZ; else @@ -108,9 +108,11 @@ static void __init lite5200_setup_arch(void) lite5200_setup_cpu(); /* Platorm specific */ #ifdef CONFIG_PCI - np = of_find_node_by_type(np, "pci"); - if (np) + np = of_find_node_by_type(NULL, "pci"); + if (np) { mpc52xx_add_bridge(np); + of_node_put(np); + } #endif #ifdef CONFIG_BLK_DEV_INITRD @@ -132,7 +134,7 @@ void lite5200_show_cpuinfo(struct seq_file *m) const char *model = NULL; if (np) - model = get_property(np, "model", NULL); + model = of_get_property(np, "model", NULL); seq_printf(m, "vendor\t\t: Freescale Semiconductor\n"); seq_printf(m, "machine\t\t: %s\n", model ? model : "unknown"); diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c index ed0cb69..2dd415f 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_common.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c @@ -60,7 +60,7 @@ mpc52xx_find_ipb_freq(struct device_node *node) of_node_get(node); while (node) { - p_ipb_freq = get_property(node, "bus-frequency", NULL); + p_ipb_freq = of_get_property(node, "bus-frequency", NULL); if (p_ipb_freq) break; diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/arch/powerpc/platforms/52xx/mpc52xx_pci.c index faf161b..34d34a2 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pci.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pci.c @@ -370,7 +370,7 @@ mpc52xx_add_bridge(struct device_node *node) return -EINVAL; } - bus_range = get_property(node, "bus-range", &len); + bus_range = of_get_property(node, "bus-range", &len); if (bus_range == NULL || len < 2 * sizeof(int)) { printk(KERN_WARNING "Can't get %s bus-range, assume bus 0\n", node->full_name); diff --git a/arch/powerpc/platforms/82xx/Kconfig b/arch/powerpc/platforms/82xx/Kconfig index 47d841e..de7fce9 100644 --- a/arch/powerpc/platforms/82xx/Kconfig +++ b/arch/powerpc/platforms/82xx/Kconfig @@ -1,21 +1,36 @@ -menu "Platform support" - depends on PPC_82xx - choice - prompt "Machine Type" - default MPC82xx_ADS + prompt "Machine Type" + depends on PPC_82xx + default MPC82xx_ADS config MPC82xx_ADS - bool "Freescale MPC82xx ADS" - select DEFAULT_UIMAGE - select PQ2ADS - select 8272 - select 8260 - select CPM2 - select FSL_SOC - help - This option enables support for the MPC8272 ADS board + bool "Freescale MPC82xx ADS" + select DEFAULT_UIMAGE + select PQ2ADS + select 8272 + select 8260 + select FSL_SOC + help + This option enables support for the MPC8272 ADS board endchoice -endmenu +config PQ2ADS + bool + default n + +config 8260 + bool + depends on 6xx + select CPM2 + help + The MPC8260 is a typical embedded CPU made by Freescale. Selecting + this option means that you wish to build a kernel for a machine with + an 8260 class CPU. + +config 8272 + bool + select 8260 + help + The MPC8272 CPM has a different internal dpram setup than other CPM2 + devices diff --git a/arch/powerpc/platforms/82xx/mpc82xx.c b/arch/powerpc/platforms/82xx/mpc82xx.c index 74e7892..cc9900d 100644 --- a/arch/powerpc/platforms/82xx/mpc82xx.c +++ b/arch/powerpc/platforms/82xx/mpc82xx.c @@ -55,17 +55,17 @@ static int __init get_freq(char *name, unsigned long *val) { struct device_node *cpu; - unsigned int *fp; + const unsigned int *fp; int found = 0; /* The cpu node should have timebase and clock frequency properties */ cpu = of_find_node_by_type(NULL, "cpu"); if (cpu) { - fp = (unsigned int *)get_property(cpu, name, NULL); + fp = of_get_property(cpu, name, NULL); if (fp) { found = 1; - *val = *fp++; + *val = *fp; } of_node_put(cpu); diff --git a/arch/powerpc/platforms/82xx/mpc82xx_ads.c b/arch/powerpc/platforms/82xx/mpc82xx_ads.c index 7334c1a..47cb09f 100644 --- a/arch/powerpc/platforms/82xx/mpc82xx_ads.c +++ b/arch/powerpc/platforms/82xx/mpc82xx_ads.c @@ -456,7 +456,7 @@ void m82xx_pci_init_irq(void) iounmap(immap); return; } - irq_map = get_property(np, "interrupt-map", &size); + irq_map = of_get_property(np, "interrupt-map", &size); if ((!irq_map) || (size <= 7)) { printk(KERN_INFO "No interrupt-map property of pci node\n"); iounmap(immap); @@ -481,7 +481,7 @@ void m82xx_pci_init_irq(void) } pci_pic_node = of_node_get(np); /* PCI interrupt controller registers: status and mask */ - regs = get_property(np, "reg", &size); + regs = of_get_property(np, "reg", &size); if ((!regs) || (size <= 2)) { printk(KERN_INFO "No reg property in pci pic node\n"); iounmap(immap); @@ -521,20 +521,20 @@ void __init add_bridge(struct device_node *np) struct pci_controller *hose; struct resource r; const int *bus_range; - const void *ptr; + const uint *ptr; memset(&r, 0, sizeof(r)); if (of_address_to_resource(np, 0, &r)) { printk(KERN_INFO "No PCI reg property in device tree\n"); return; } - if (!(ptr = get_property(np, "clock-frequency", NULL))) { + if (!(ptr = of_get_property(np, "clock-frequency", NULL))) { printk(KERN_INFO "No clock-frequency property in PCI node"); return; } - pci_clk_frq = *(uint *) ptr; + pci_clk_frq = *ptr; of_node_put(np); - bus_range = get_property(np, "bus-range", &len); + bus_range = of_get_property(np, "bus-range", &len); if (bus_range == NULL || len < 2 * sizeof(int)) { printk(KERN_WARNING "Can't get bus-range for %s, assume" " bus 0\n", np->full_name); diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig index 713b31a..19cafdf 100644 --- a/arch/powerpc/platforms/83xx/Kconfig +++ b/arch/powerpc/platforms/83xx/Kconfig @@ -1,8 +1,6 @@ -menu "Platform support" - depends on PPC_83xx - choice prompt "Machine Type" + depends on PPC_83xx default MPC834x_MDS config MPC8313_RDB @@ -18,6 +16,13 @@ config MPC832x_MDS help This option enables support for the MPC832x MDS evaluation board. +config MPC832x_RDB + bool "Freescale MPC832x RDB" + select DEFAULT_UIMAGE + select QUICC_ENGINE + help + This option enables support for the MPC8323 RDB board. + config MPC834x_MDS bool "Freescale MPC834x MDS" select DEFAULT_UIMAGE @@ -57,7 +62,7 @@ config PPC_MPC832x bool select PPC_UDBG_16550 select PPC_INDIRECT_PCI - default y if MPC832x_MDS + default y if MPC832x_MDS || MPC832x_RDB config MPC834x bool @@ -70,5 +75,3 @@ config PPC_MPC836x select PPC_UDBG_16550 select PPC_INDIRECT_PCI default y if MPC836x_MDS - -endmenu diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile index dfc970d..31a91b5 100644 --- a/arch/powerpc/platforms/83xx/Makefile +++ b/arch/powerpc/platforms/83xx/Makefile @@ -4,6 +4,7 @@ obj-y := misc.o obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_MPC8313_RDB) += mpc8313_rdb.o +obj-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.o obj-$(CONFIG_MPC834x_MDS) += mpc834x_mds.o obj-$(CONFIG_MPC834x_ITX) += mpc834x_itx.o obj-$(CONFIG_MPC836x_MDS) += mpc836x_mds.o diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c index 17e3a3c..fff09f5 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c @@ -41,7 +41,6 @@ #include <asm/qe_ic.h> #include "mpc83xx.h" -#include "mpc832x_mds.h" #undef DEBUG #ifdef DEBUG diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.h b/arch/powerpc/platforms/83xx/mpc832x_mds.h deleted file mode 100644 index a495889..0000000 --- a/arch/powerpc/platforms/83xx/mpc832x_mds.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved. - * - * Description: - * MPC832x MDS board specific header. - * - * 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. - * - */ - -#ifndef __MACH_MPC832x_MDS_H__ -#define __MACH_MPC832x_MDS_H__ - -extern u8 *get_bcsr(void); - -#endif /* __MACH_MPC832x_MDS_H__ */ diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c new file mode 100644 index 0000000..6b71e9f --- /dev/null +++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c @@ -0,0 +1,138 @@ +/* + * arch/powerpc/platforms/83xx/mpc832x_rdb.c + * + * Copyright (C) Freescale Semiconductor, Inc. 2007. All rights reserved. + * + * Description: + * MPC832x RDB board specific routines. + * This file is based on mpc832x_mds.c and mpc8313_rdb.c + * Author: Michael Barkowski <michael.barkowski@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 <linux/pci.h> + +#include <asm/of_platform.h> +#include <asm/time.h> +#include <asm/ipic.h> +#include <asm/udbg.h> +#include <asm/qe.h> +#include <asm/qe_ic.h> + +#include "mpc83xx.h" + +#undef DEBUG +#ifdef DEBUG +#define DBG(fmt...) udbg_printf(fmt) +#else +#define DBG(fmt...) +#endif + +#ifndef CONFIG_PCI +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +#endif + +/* ************************************************************************ + * + * Setup the architecture + * + */ +static void __init mpc832x_rdb_setup_arch(void) +{ + struct device_node *np; + + if (ppc_md.progress) + ppc_md.progress("mpc832x_rdb_setup_arch()", 0); + +#ifdef CONFIG_PCI + for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) + add_bridge(np); + + ppc_md.pci_exclude_device = mpc83xx_exclude_device; +#endif + +#ifdef CONFIG_QUICC_ENGINE + qe_reset(); + + if ((np = of_find_node_by_name(np, "par_io")) != NULL) { + par_io_init(np); + of_node_put(np); + + for (np = NULL; (np = of_find_node_by_name(np, "ucc")) != NULL;) + par_io_of_config(np); + } +#endif /* CONFIG_QUICC_ENGINE */ +} + +static struct of_device_id mpc832x_ids[] = { + { .type = "soc", }, + { .compatible = "soc", }, + { .type = "qe", }, + {}, +}; + +static int __init mpc832x_declare_of_platform_devices(void) +{ + if (!machine_is(mpc832x_rdb)) + return 0; + + /* Publish the QE devices */ + of_platform_bus_probe(NULL, mpc832x_ids, NULL); + + return 0; +} +device_initcall(mpc832x_declare_of_platform_devices); + +void __init mpc832x_rdb_init_IRQ(void) +{ + + struct device_node *np; + + np = of_find_node_by_type(NULL, "ipic"); + if (!np) + return; + + ipic_init(np, 0); + + /* Initialize the default interrupt mapping priorities, + * in case the boot rom changed something on us. + */ + ipic_set_default_priority(); + of_node_put(np); + +#ifdef CONFIG_QUICC_ENGINE + np = of_find_node_by_type(NULL, "qeic"); + if (!np) + return; + + qe_ic_init(np, 0); + of_node_put(np); +#endif /* CONFIG_QUICC_ENGINE */ +} + +/* + * Called very early, MMU is off, device-tree isn't unflattened + */ +static int __init mpc832x_rdb_probe(void) +{ + unsigned long root = of_get_flat_dt_root(); + + return of_flat_dt_is_compatible(root, "MPC832xRDB"); +} + +define_machine(mpc832x_rdb) { + .name = "MPC832x RDB", + .probe = mpc832x_rdb_probe, + .setup_arch = mpc832x_rdb_setup_arch, + .init_IRQ = mpc832x_rdb_init_IRQ, + .get_irq = ipic_get_irq, + .restart = mpc83xx_restart, + .time_init = mpc83xx_time_init, + .calibrate_decr = generic_calibrate_decr, + .progress = udbg_progress, +}; diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.h b/arch/powerpc/platforms/83xx/mpc834x_itx.h deleted file mode 100644 index 174ca4e..0000000 --- a/arch/powerpc/platforms/83xx/mpc834x_itx.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * arch/powerpc/platforms/83xx/mpc834x_itx.h - * - * MPC834X ITX common board definitions - * - * Maintainer: Kumar Gala <galak@kernel.crashing.org> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#ifndef __MACH_MPC83XX_ITX_H__ -#define __MACH_MPC83XX_ITX_H__ - -#define PIRQA MPC83xx_IRQ_EXT4 -#define PIRQB MPC83xx_IRQ_EXT5 -#define PIRQC MPC83xx_IRQ_EXT6 -#define PIRQD MPC83xx_IRQ_EXT7 - -#endif /* __MACH_MPC83XX_ITX_H__ */ diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c index 9c36505..774457d0 100644 --- a/arch/powerpc/platforms/83xx/pci.c +++ b/arch/powerpc/platforms/83xx/pci.c @@ -60,7 +60,7 @@ int __init add_bridge(struct device_node *dev) has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); /* Get bus range if any */ - 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)) { printk(KERN_WARNING "Can't get bus-range for %s, assume" " bus 0\n", dev->full_name); diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index e764c0a..629926e 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig @@ -1,8 +1,6 @@ -menu "Platform support" - depends on PPC_85xx - choice prompt "Machine Type" + depends on PPC_85xx default MPC8540_ADS config MPC8540_ADS @@ -30,6 +28,12 @@ config MPC85xx_MDS help This option enables support for the MPC85xx MDS board +config MPC8544_DS + bool "Freescale MPC8544 DS" + select DEFAULT_UIMAGE + help + This option enables support for the MPC8544 DS board + endchoice config MPC8540 @@ -40,33 +44,15 @@ config MPC8540 config MPC8560 bool - select PPC_INDIRECT_PCI + select CPM2 default y if MPC8560_ADS config MPC85xx bool select PPC_UDBG_16550 select PPC_INDIRECT_PCI + select PPC_INDIRECT_PCI_BE + select MPIC select SERIAL_8250_SHARE_IRQ if SERIAL_8250 - default y if MPC8540_ADS || MPC85xx_CDS || MPC8560_ADS || MPC85xx_MDS - -config PPC_INDIRECT_PCI_BE - bool - depends on PPC_85xx - default y - -config MPIC - bool - default y - -config CPM2 - bool - depends on MPC8560 - default y - help - The CPM2 (Communications Processor Module) is a coprocessor on - embedded CPUs made by Motorola. Selecting this option means that - you wish to build a kernel for a machine with a CPM2 coprocessor - on it. - -endmenu + default y if MPC8540_ADS || MPC85xx_CDS || MPC8560_ADS \ + || MPC85xx_MDS || MPC8544_DS diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index 4e63917..4e02cbb 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile @@ -5,4 +5,5 @@ obj-$(CONFIG_PPC_85xx) += misc.o pci.o obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o +obj-$(CONFIG_MPC8544_DS) += mpc8544_ds.o obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o diff --git a/arch/powerpc/platforms/85xx/mpc8544_ds.c b/arch/powerpc/platforms/85xx/mpc8544_ds.c new file mode 100644 index 0000000..2867f85 --- /dev/null +++ b/arch/powerpc/platforms/85xx/mpc8544_ds.c @@ -0,0 +1,144 @@ +/* + * MPC8544 DS Board Setup + * + * Author Xianghua Xiao (x.xiao@freescale.com) + * 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. + */ + +#include <linux/stddef.h> +#include <linux/kernel.h> +#include <linux/kdev_t.h> +#include <linux/delay.h> +#include <linux/seq_file.h> + +#include <asm/system.h> +#include <asm/time.h> +#include <asm/machdep.h> +#include <asm/mpc85xx.h> +#include <mm/mmu_decl.h> +#include <asm/prom.h> +#include <asm/udbg.h> +#include <asm/mpic.h> +#include <asm/i8259.h> + +#include <sysdev/fsl_soc.h> +#include "mpc85xx.h" + +#undef DEBUG + +#ifdef DEBUG +#define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args) +#else +#define DBG(fmt, args...) +#endif + + +void __init mpc8544_ds_pic_init(void) +{ + struct mpic *mpic; + struct resource r; + struct device_node *np = NULL; +#ifdef CONFIG_PPC_I8259 + struct device_node *cascade_node = NULL; + int cascade_irq; +#endif + + np = of_find_node_by_type(np, "open-pic"); + + if (np == NULL) { + printk(KERN_ERR "Could not find open-pic node\n"); + return; + } + + if (of_address_to_resource(np, 0, &r)) { + printk(KERN_ERR "Failed to map mpic register space\n"); + of_node_put(np); + return; + } + + /* Alloc mpic structure and per isu has 16 INT entries. */ + mpic = mpic_alloc(np, r.start, + MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, + 16, 64, " OPENPIC "); + BUG_ON(mpic == NULL); + + /* + * 48 Internal Interrupts + */ + mpic_assign_isu(mpic, 0, r.start + 0x10200); + mpic_assign_isu(mpic, 1, r.start + 0x10400); + mpic_assign_isu(mpic, 2, r.start + 0x10600); + + /* + * 16 External interrupts + */ + mpic_assign_isu(mpic, 3, r.start + 0x10000); + + mpic_init(mpic); + +#ifdef CONFIG_PPC_I8259 + /* Initialize the i8259 controller */ + for_each_node_by_type(np, "interrupt-controller") + if (device_is_compatible(np, "chrp,iic")) { + cascade_node = np; + break; + } + + if (cascade_node == NULL) { + printk(KERN_DEBUG "Could not find i8259 PIC\n"); + return; + } + + cascade_irq = irq_of_parse_and_map(cascade_node, 0); + if (cascade_irq == NO_IRQ) { + printk(KERN_ERR "Failed to map cascade interrupt\n"); + return; + } + + DBG("mpc8544ds: cascade mapped to irq %d\n", cascade_irq); + + i8259_init(cascade_node, 0); + of_node_put(cascade_node); + + set_irq_chained_handler(cascade_irq, mpc8544_8259_cascade); +#endif /* CONFIG_PPC_I8259 */ +} + + +/* + * Setup the architecture + */ +static void __init mpc8544_ds_setup_arch(void) +{ + if (ppc_md.progress) + ppc_md.progress("mpc8544_ds_setup_arch()", 0); + + printk("MPC8544 DS board from Freescale Semiconductor\n"); +} + + +/* + * Called very early, device-tree isn't unflattened + */ +static int __init mpc8544_ds_probe(void) +{ + unsigned long root = of_get_flat_dt_root(); + + return of_flat_dt_is_compatible(root, "MPC8544DS"); +} + +define_machine(mpc8544_ds) { + .name = "MPC8544 DS", + .probe = mpc8544_ds_probe, + .setup_arch = mpc8544_ds_setup_arch, + .init_IRQ = mpc8544_ds_pic_init, + .get_irq = mpic_get_irq, + .restart = mpc85xx_restart, + .calibrate_decr = generic_calibrate_decr, + .progress = udbg_progress, +}; diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c index 8ed034a..5d27621 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c @@ -227,7 +227,7 @@ static void __init mpc85xx_ads_setup_arch(void) if (cpu != 0) { const unsigned int *fp; - fp = get_property(cpu, "clock-frequency", NULL); + fp = of_get_property(cpu, "clock-frequency", NULL); if (fp != 0) loops_per_jiffy = *fp / HZ; else diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c index 4232686..7e71636 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c @@ -237,7 +237,7 @@ static void __init mpc85xx_cds_setup_arch(void) if (cpu != 0) { const unsigned int *fp; - fp = get_property(cpu, "clock-frequency", NULL); + fp = of_get_property(cpu, "clock-frequency", NULL); if (fp != 0) loops_per_jiffy = *fp / HZ; else diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c index 81144d2..54db416 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c @@ -80,7 +80,7 @@ static void __init mpc85xx_mds_setup_arch(void) np = of_find_node_by_type(NULL, "cpu"); if (np != NULL) { const unsigned int *fp = - get_property(np, "clock-frequency", NULL); + of_get_property(np, "clock-frequency", NULL); if (fp != NULL) loops_per_jiffy = *fp / HZ; else diff --git a/arch/powerpc/platforms/85xx/pci.c b/arch/powerpc/platforms/85xx/pci.c index 05930ee..48f17e2 100644 --- a/arch/powerpc/platforms/85xx/pci.c +++ b/arch/powerpc/platforms/85xx/pci.c @@ -51,7 +51,7 @@ int __init add_bridge(struct device_node *dev) has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); /* Get bus range if any */ - 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)) { printk(KERN_WARNING "Can't get bus-range for %s, assume" " bus 0\n", dev->full_name); diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig index 0c70944..d1bcff5 100644 --- a/arch/powerpc/platforms/86xx/Kconfig +++ b/arch/powerpc/platforms/86xx/Kconfig @@ -1,8 +1,6 @@ -menu "Platform Support" - depends on PPC_86xx - choice prompt "Machine Type" + depends on PPC_86xx default MPC8641_HPCN config MPC8641_HPCN @@ -14,20 +12,10 @@ config MPC8641_HPCN endchoice - config MPC8641 bool select PPC_INDIRECT_PCI + select PPC_INDIRECT_PCI_BE select PPC_UDBG_16550 + select MPIC default y if MPC8641_HPCN - -config MPIC - bool - default y - -config PPC_INDIRECT_PCI_BE - bool - depends on PPC_86xx - default y - -endmenu diff --git a/arch/powerpc/platforms/86xx/Makefile b/arch/powerpc/platforms/86xx/Makefile index 476a6ee..418fd8f 100644 --- a/arch/powerpc/platforms/86xx/Makefile +++ b/arch/powerpc/platforms/86xx/Makefile @@ -4,4 +4,4 @@ obj-$(CONFIG_SMP) += mpc86xx_smp.o obj-$(CONFIG_MPC8641_HPCN) += mpc86xx_hpcn.o -obj-$(CONFIG_PCI) += pci.o mpc86xx_pcie.o +obj-$(CONFIG_PCI) += pci.o diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c index f42f801..3d3d98f 100644 --- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c +++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c @@ -349,7 +349,7 @@ mpc86xx_hpcn_setup_arch(void) if (np != 0) { const unsigned int *fp; - fp = get_property(np, "clock-frequency", NULL); + fp = of_get_property(np, "clock-frequency", NULL); if (fp != 0) loops_per_jiffy = *fp / HZ; else @@ -384,7 +384,7 @@ mpc86xx_hpcn_show_cpuinfo(struct seq_file *m) root = of_find_node_by_path("/"); if (root) - model = get_property(root, "model", NULL); + model = of_get_property(root, "model", NULL); seq_printf(m, "Machine\t\t: %s\n", model); of_node_put(root); diff --git a/arch/powerpc/platforms/86xx/pci.c b/arch/powerpc/platforms/86xx/pci.c index 481e18e..8235c56 100644 --- a/arch/powerpc/platforms/86xx/pci.c +++ b/arch/powerpc/platforms/86xx/pci.c @@ -22,9 +22,9 @@ #include <asm/atomic.h> #include <asm/io.h> #include <asm/prom.h> -#include <asm/immap_86xx.h> #include <asm/pci-bridge.h> #include <sysdev/fsl_soc.h> +#include <sysdev/fsl_pcie.h> #include "mpc86xx.h" @@ -163,7 +163,7 @@ int __init add_bridge(struct device_node *dev) has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); /* Get bus range if any */ - 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)) printk(KERN_WARNING "Can't get bus-range for %s, assume" " bus 0\n", dev->full_name); diff --git a/arch/powerpc/platforms/8xx/Kconfig b/arch/powerpc/platforms/8xx/Kconfig index beea683..39bb8c5 100644 --- a/arch/powerpc/platforms/8xx/Kconfig +++ b/arch/powerpc/platforms/8xx/Kconfig @@ -1,6 +1,3 @@ -menu "Platform support" - depends on PPC_8xx - config FADS bool @@ -9,6 +6,7 @@ config CPM1 choice prompt "8xx Machine Type" + depends on PPC_8xx depends on 8xx default MPC885ADS @@ -36,38 +34,36 @@ config MPC885ADS endchoice menu "Freescale Ethernet driver platform-specific options" - depends on (FS_ENET && MPC885ADS) - - config MPC8xx_SECOND_ETH - bool "Second Ethernet channel" - depends on MPC885ADS - default y - help - This enables support for second Ethernet on MPC885ADS and MPC86xADS boards. - The latter will use SCC1, for 885ADS you can select it below. - - choice - prompt "Second Ethernet channel" - depends on MPC8xx_SECOND_ETH - default MPC8xx_SECOND_ETH_FEC2 - - config MPC8xx_SECOND_ETH_FEC2 - bool "FEC2" - depends on MPC885ADS - help - Enable FEC2 to serve as 2-nd Ethernet channel. Note that SMC2 - (often 2-nd UART) will not work if this is enabled. - - config MPC8xx_SECOND_ETH_SCC3 - bool "SCC3" - depends on MPC885ADS - help - Enable SCC3 to serve as 2-nd Ethernet channel. Note that SMC1 - (often 1-nd UART) will not work if this is enabled. - - endchoice + depends on (FS_ENET && MPC885ADS) -endmenu + config MPC8xx_SECOND_ETH + bool "Second Ethernet channel" + depends on MPC885ADS + default y + help + This enables support for second Ethernet on MPC885ADS and MPC86xADS boards. + The latter will use SCC1, for 885ADS you can select it below. + + choice + prompt "Second Ethernet channel" + depends on MPC8xx_SECOND_ETH + default MPC8xx_SECOND_ETH_FEC2 + + config MPC8xx_SECOND_ETH_FEC2 + bool "FEC2" + depends on MPC885ADS + help + Enable FEC2 to serve as 2-nd Ethernet channel. Note that SMC2 + (often 2-nd UART) will not work if this is enabled. + + config MPC8xx_SECOND_ETH_SCC3 + bool "SCC3" + depends on MPC885ADS + help + Enable SCC3 to serve as 2-nd Ethernet channel. Note that SMC1 + (often 1-nd UART) will not work if this is enabled. + + endchoice endmenu @@ -98,7 +94,7 @@ config 8xx_CPU6 require workarounds for Linux (and most other OSes to work). If you get a BUG() very early in boot, this might fix the problem. For more details read the document entitled "MPC860 Family Device Errata - Reference" on Motorola's website. This option also incurs a + Reference" on Freescale's website. This option also incurs a performance hit. If in doubt, say N here. @@ -135,4 +131,3 @@ config UCODE_PATCH depends on !NO_UCODE_PATCH endmenu - diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c index 9ed7125..0901dba 100644 --- a/arch/powerpc/platforms/8xx/m8xx_setup.c +++ b/arch/powerpc/platforms/8xx/m8xx_setup.c @@ -85,17 +85,17 @@ init_internal_rtc(void) static int __init get_freq(char *name, unsigned long *val) { struct device_node *cpu; - unsigned int *fp; + const unsigned int *fp; int found = 0; /* The cpu node should have timebase and clock frequency properties */ cpu = of_find_node_by_type(NULL, "cpu"); if (cpu) { - fp = (unsigned int *)get_property(cpu, name, NULL); + fp = of_get_property(cpu, name, NULL); if (fp) { found = 1; - *val = *fp++; + *val = *fp; } of_node_put(cpu); @@ -262,7 +262,7 @@ void mpc8xx_show_cpuinfo(struct seq_file *m) root = of_find_node_by_path("/"); if (root) - model = get_property(root, "model", NULL); + model = of_get_property(root, "model", NULL); seq_printf(m, "Machine\t\t: %s\n", model); of_node_put(root); diff --git a/arch/powerpc/platforms/8xx/mpc86xads.h b/arch/powerpc/platforms/8xx/mpc86xads.h index b5d19dd..59bad2f 100644 --- a/arch/powerpc/platforms/8xx/mpc86xads.h +++ b/arch/powerpc/platforms/8xx/mpc86xads.h @@ -37,7 +37,7 @@ #define CPM_MAP_ADDR (get_immrbase() + MPC8xx_CPM_OFFSET) #define CPM_IRQ_OFFSET 16 // for compability with cpm_uart driver -#define PCMCIA_MEM_ADDR (uint)0xff020000) +#define PCMCIA_MEM_ADDR ((uint)0xff020000) #define PCMCIA_MEM_SIZE ((uint)(64 * 1024)) /* Bits of interest in the BCSRs. diff --git a/arch/powerpc/platforms/8xx/mpc86xads_setup.c b/arch/powerpc/platforms/8xx/mpc86xads_setup.c index ef52ce7..a35315a 100644 --- a/arch/powerpc/platforms/8xx/mpc86xads_setup.c +++ b/arch/powerpc/platforms/8xx/mpc86xads_setup.c @@ -247,7 +247,7 @@ void init_smc_ioports(struct fs_uart_platform_info *data) } } -int platform_device_skip(char *model, int id) +int platform_device_skip(const char *model, int id) { return 0; } @@ -260,7 +260,7 @@ static void __init mpc86xads_setup_arch(void) if (cpu != 0) { const unsigned int *fp; - fp = get_property(cpu, "clock-frequency", NULL); + fp = of_get_property(cpu, "clock-frequency", NULL); if (fp != 0) loops_per_jiffy = *fp / HZ; else diff --git a/arch/powerpc/platforms/8xx/mpc885ads.h b/arch/powerpc/platforms/8xx/mpc885ads.h index 30cbebf..7c31aec 100644 --- a/arch/powerpc/platforms/8xx/mpc885ads.h +++ b/arch/powerpc/platforms/8xx/mpc885ads.h @@ -37,7 +37,7 @@ #define CPM_MAP_ADDR (get_immrbase() + MPC8xx_CPM_OFFSET) #define CPM_IRQ_OFFSET 16 // for compability with cpm_uart driver -#define PCMCIA_MEM_ADDR (uint)0xff020000) +#define PCMCIA_MEM_ADDR ((uint)0xff020000) #define PCMCIA_MEM_SIZE ((uint)(64 * 1024)) /* Bits of interest in the BCSRs. diff --git a/arch/powerpc/platforms/8xx/mpc885ads_setup.c b/arch/powerpc/platforms/8xx/mpc885ads_setup.c index c5fefdf6..a57b577 100644 --- a/arch/powerpc/platforms/8xx/mpc885ads_setup.c +++ b/arch/powerpc/platforms/8xx/mpc885ads_setup.c @@ -322,7 +322,7 @@ void init_smc_ioports(struct fs_uart_platform_info *data) } } -int platform_device_skip(char *model, int id) +int platform_device_skip(const char *model, int id) { #ifdef CONFIG_MPC8xx_SECOND_ETH_SCC3 const char *dev = "FEC"; @@ -346,7 +346,7 @@ static void __init mpc885ads_setup_arch(void) if (cpu != 0) { const unsigned int *fp; - fp = get_property(cpu, "clock-frequency", NULL); + fp = of_get_property(cpu, "clock-frequency", NULL); if (fp != 0) loops_per_jiffy = *fp / HZ; else diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig new file mode 100644 index 0000000..51e3334 --- /dev/null +++ b/arch/powerpc/platforms/Kconfig @@ -0,0 +1,259 @@ +menu "Platform support" + +choice + prompt "Machine type" + depends on PPC64 || CLASSIC32 + 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 + +source "arch/powerpc/platforms/pseries/Kconfig" +source "arch/powerpc/platforms/iseries/Kconfig" +source "arch/powerpc/platforms/chrp/Kconfig" +source "arch/powerpc/platforms/52xx/Kconfig" +source "arch/powerpc/platforms/powermac/Kconfig" +source "arch/powerpc/platforms/prep/Kconfig" +source "arch/powerpc/platforms/maple/Kconfig" +source "arch/powerpc/platforms/pasemi/Kconfig" +source "arch/powerpc/platforms/celleb/Kconfig" +source "arch/powerpc/platforms/ps3/Kconfig" +source "arch/powerpc/platforms/cell/Kconfig" +source "arch/powerpc/platforms/8xx/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/embedded6xx/Kconfig" +#source "arch/powerpc/platforms/4xx/Kconfig + +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 MPIC + bool + default n + +config MPIC_WEIRD + bool + default n + +config PPC_I8259 + bool + default n + +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_U3_HT_IRQS + 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" + +menu "CPU Frequency drivers" + depends on CPU_FREQ + +config CPU_FREQ_PMAC + bool "Support for Apple PowerBooks" + depends on 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 PPC_PMAC && 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 PPC_PASEMI_CPUFREQ + bool "Support for PA Semi PWRficient" + depends on PPC_PASEMI + default y + select CPU_FREQ_TABLE + help + This adds the support for frequency switching on PA Semi + PWRficient processors. + +endmenu + +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 CLASSIC32 + 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. + +config QUICC_ENGINE + bool + 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 CPM2 + bool + default n + help + The CPM2 (Communications Processor Module) is a coprocessor on + embedded CPUs made by Freescale. Selecting this option means that + you wish to build a kernel for a machine with a CPM2 coprocessor + on it (826x, 827x, 8560). + +endmenu diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig index 06a85b7..8255177 100644 --- a/arch/powerpc/platforms/cell/Kconfig +++ b/arch/powerpc/platforms/cell/Kconfig @@ -1,3 +1,26 @@ +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 + menu "Cell Broadband Engine options" depends on PPC_CELL @@ -18,6 +41,7 @@ config SPU_BASE config CBE_RAS bool "RAS features for bare metal Cell BE" + depends on PPC_CELL_NATIVE default y config CBE_THERM diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq.c b/arch/powerpc/platforms/cell/cbe_cpufreq.c index a3850fd..f9ac3fe 100644 --- a/arch/powerpc/platforms/cell/cbe_cpufreq.c +++ b/arch/powerpc/platforms/cell/cbe_cpufreq.c @@ -25,9 +25,12 @@ #include <asm/hw_irq.h> #include <asm/io.h> +#include <asm/machdep.h> #include <asm/processor.h> #include <asm/prom.h> #include <asm/time.h> +#include <asm/pmi.h> +#include <asm/of_platform.h> #include "cbe_regs.h" @@ -68,6 +71,38 @@ static u64 MIC_Slow_Next_Timer_table[] = { * hardware specific functions */ +static struct of_device *pmi_dev; + +static int set_pmode_pmi(int cpu, unsigned int pmode) +{ + int ret; + pmi_message_t pmi_msg; +#ifdef DEBUG + u64 time; +#endif + + pmi_msg.type = PMI_TYPE_FREQ_CHANGE; + pmi_msg.data1 = cbe_cpu_to_node(cpu); + pmi_msg.data2 = pmode; + +#ifdef DEBUG + time = (u64) get_cycles(); +#endif + + pmi_send_message(pmi_dev, pmi_msg); + ret = pmi_msg.data2; + + pr_debug("PMI returned slow mode %d\n", ret); + +#ifdef DEBUG + time = (u64) get_cycles() - time; /* actual cycles (not cpu cycles!) */ + time = 1000000000 * time / CLOCK_TICK_RATE; /* time in ns (10^-9) */ + pr_debug("had to wait %lu ns for a transition\n", time); +#endif + return ret; +} + + static int get_pmode(int cpu) { int ret; @@ -79,7 +114,7 @@ static int get_pmode(int cpu) return ret; } -static int set_pmode(int cpu, unsigned int pmode) +static int set_pmode_reg(int cpu, unsigned int pmode) { struct cbe_pmd_regs __iomem *pmd_regs; struct cbe_mic_tm_regs __iomem *mic_tm_regs; @@ -120,37 +155,71 @@ static int set_pmode(int cpu, unsigned int pmode) return 0; } +static int set_pmode(int cpu, unsigned int slow_mode) { + if (pmi_dev) + return set_pmode_pmi(cpu, slow_mode); + else + return set_pmode_reg(cpu, slow_mode); +} + +static void cbe_cpufreq_handle_pmi(struct of_device *dev, pmi_message_t pmi_msg) +{ + struct cpufreq_policy policy; + u8 cpu; + u8 cbe_pmode_new; + + BUG_ON(pmi_msg.type != PMI_TYPE_FREQ_CHANGE); + + cpu = cbe_node_to_cpu(pmi_msg.data1); + cbe_pmode_new = pmi_msg.data2; + + cpufreq_get_policy(&policy, cpu); + + policy.max = min(policy.max, cbe_freqs[cbe_pmode_new].frequency); + policy.min = min(policy.min, policy.max); + + pr_debug("cbe_handle_pmi: new policy.min=%d policy.max=%d\n", policy.min, policy.max); + cpufreq_set_policy(&policy); +} + +static struct pmi_handler cbe_pmi_handler = { + .type = PMI_TYPE_FREQ_CHANGE, + .handle_pmi_message = cbe_cpufreq_handle_pmi, +}; + + /* * cpufreq functions */ -static int cbe_cpufreq_cpu_init (struct cpufreq_policy *policy) +static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy) { - u32 *max_freq; + const u32 *max_freqp; + u32 max_freq; int i, cur_pmode; struct device_node *cpu; cpu = of_get_cpu_node(policy->cpu, NULL); - if(!cpu) + if (!cpu) return -ENODEV; pr_debug("init cpufreq on CPU %d\n", policy->cpu); - max_freq = (u32*) get_property(cpu, "clock-frequency", NULL); + max_freqp = of_get_property(cpu, "clock-frequency", NULL); - if(!max_freq) + if (!max_freqp) return -EINVAL; - // we need the freq in kHz - *max_freq /= 1000; + /* we need the freq in kHz */ + max_freq = *max_freqp / 1000; - pr_debug("max clock-frequency is at %u kHz\n", *max_freq); + pr_debug("max clock-frequency is at %u kHz\n", max_freq); pr_debug("initializing frequency table\n"); - // initialize frequency table + /* initialize frequency table */ for (i=0; cbe_freqs[i].frequency!=CPUFREQ_TABLE_END; i++) { - cbe_freqs[i].frequency = *max_freq / cbe_freqs[i].index; + cbe_freqs[i].frequency = max_freq / cbe_freqs[i].index; pr_debug("%d: %d\n", i, cbe_freqs[i].frequency); } @@ -167,10 +236,10 @@ static int cbe_cpufreq_cpu_init (struct cpufreq_policy *policy) policy->cpus = cpu_sibling_map[policy->cpu]; #endif - cpufreq_frequency_table_get_attr (cbe_freqs, policy->cpu); + cpufreq_frequency_table_get_attr(cbe_freqs, policy->cpu); /* this ensures that policy->cpuinfo_min and policy->cpuinfo_max are set correctly */ - return cpufreq_frequency_table_cpuinfo (policy, cbe_freqs); + return cpufreq_frequency_table_cpuinfo(policy, cbe_freqs); } static int cbe_cpufreq_cpu_exit(struct cpufreq_policy *policy) @@ -202,7 +271,7 @@ static int cbe_cpufreq_target(struct cpufreq_policy *policy, unsigned int target freqs.new = cbe_freqs[cbe_pmode_new].frequency; freqs.cpu = policy->cpu; - mutex_lock (&cbe_switch_mutex); + mutex_lock(&cbe_switch_mutex); cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); pr_debug("setting frequency for cpu %d to %d kHz, 1/%d of max frequency\n", @@ -233,11 +302,26 @@ static struct cpufreq_driver cbe_cpufreq_driver = { static int __init cbe_cpufreq_init(void) { + struct device_node *np; + + if (!machine_is(cell)) + return -ENODEV; + + np = of_find_node_by_type(NULL, "ibm,pmi"); + + pmi_dev = of_find_device_by_node(np); + + if (pmi_dev) + pmi_register_handler(pmi_dev, &cbe_pmi_handler); + return cpufreq_register_driver(&cbe_cpufreq_driver); } static void __exit cbe_cpufreq_exit(void) { + if (pmi_dev) + pmi_unregister_handler(pmi_dev, &cbe_pmi_handler); + cpufreq_unregister_driver(&cbe_cpufreq_driver); } diff --git a/arch/powerpc/platforms/cell/cbe_regs.c b/arch/powerpc/platforms/cell/cbe_regs.c index 9a0ee62..12c9674 100644 --- a/arch/powerpc/platforms/cell/cbe_regs.c +++ b/arch/powerpc/platforms/cell/cbe_regs.c @@ -14,6 +14,8 @@ #include <asm/pgtable.h> #include <asm/prom.h> #include <asm/ptrace.h> +#include <asm/of_device.h> +#include <asm/of_platform.h> #include "cbe_regs.h" @@ -27,6 +29,7 @@ static struct cbe_regs_map { struct device_node *cpu_node; + struct device_node *be_node; struct cbe_pmd_regs __iomem *pmd_regs; struct cbe_iic_regs __iomem *iic_regs; struct cbe_mic_tm_regs __iomem *mic_tm_regs; @@ -37,30 +40,43 @@ static int cbe_regs_map_count; static struct cbe_thread_map { struct device_node *cpu_node; + struct device_node *be_node; struct cbe_regs_map *regs; + unsigned int thread_id; + unsigned int cbe_id; } cbe_thread_map[NR_CPUS]; +static cpumask_t cbe_local_mask[MAX_CBE] = { [0 ... MAX_CBE-1] = CPU_MASK_NONE }; +static cpumask_t cbe_first_online_cpu = CPU_MASK_NONE; + static struct cbe_regs_map *cbe_find_map(struct device_node *np) { int i; struct device_node *tmp_np; - if (strcasecmp(np->type, "spe") == 0) { - if (np->data == NULL) { - /* walk up path until cpu node was found */ - tmp_np = np->parent; - while (tmp_np != NULL && strcasecmp(tmp_np->type, "cpu") != 0) - tmp_np = tmp_np->parent; + if (strcasecmp(np->type, "spe")) { + for (i = 0; i < cbe_regs_map_count; i++) + if (cbe_regs_maps[i].cpu_node == np || + cbe_regs_maps[i].be_node == np) + return &cbe_regs_maps[i]; + return NULL; + } - np->data = cbe_find_map(tmp_np); - } + if (np->data) return np->data; - } - for (i = 0; i < cbe_regs_map_count; i++) - if (cbe_regs_maps[i].cpu_node == np) - return &cbe_regs_maps[i]; - return NULL; + /* walk up path until cpu or be node was found */ + tmp_np = np; + do { + tmp_np = tmp_np->parent; + /* on a correct devicetree we wont get up to root */ + BUG_ON(!tmp_np); + } while (strcasecmp(tmp_np->type, "cpu") && + strcasecmp(tmp_np->type, "be")); + + np->data = cbe_find_map(tmp_np); + + return np->data; } struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np) @@ -130,38 +146,105 @@ struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu) } EXPORT_SYMBOL_GPL(cbe_get_cpu_mic_tm_regs); -/* FIXME - * This is little more than a stub at the moment. It should be - * fleshed out so that it works for both SMT and non-SMT, no - * matter if the passed cpu is odd or even. - * For SMT enabled, returns 0 for even-numbered cpu; otherwise 1. - * For SMT disabled, returns 0 for all cpus. - */ u32 cbe_get_hw_thread_id(int cpu) { - return (cpu & 1); + return cbe_thread_map[cpu].thread_id; } EXPORT_SYMBOL_GPL(cbe_get_hw_thread_id); -void __init cbe_regs_init(void) +u32 cbe_cpu_to_node(int cpu) { - int i; - struct device_node *cpu; + return cbe_thread_map[cpu].cbe_id; +} +EXPORT_SYMBOL_GPL(cbe_cpu_to_node); - /* Build local fast map of CPUs */ - for_each_possible_cpu(i) - cbe_thread_map[i].cpu_node = of_get_cpu_node(i, NULL); +u32 cbe_node_to_cpu(int node) +{ + return find_first_bit( (unsigned long *) &cbe_local_mask[node], sizeof(cpumask_t)); +} +EXPORT_SYMBOL_GPL(cbe_node_to_cpu); - /* Find maps for each device tree CPU */ - for_each_node_by_type(cpu, "cpu") { - struct cbe_regs_map *map = &cbe_regs_maps[cbe_regs_map_count++]; +static struct device_node *cbe_get_be_node(int cpu_id) +{ + struct device_node *np; + + for_each_node_by_type (np, "be") { + int len,i; + const phandle *cpu_handle; + + cpu_handle = of_get_property(np, "cpus", &len); + + for (i=0; i<len; i++) + if (of_find_node_by_phandle(cpu_handle[i]) == of_get_cpu_node(cpu_id, NULL)) + return np; + } + + return NULL; +} + +void __init cbe_fill_regs_map(struct cbe_regs_map *map) +{ + if(map->be_node) { + struct device_node *be, *np; + + be = map->be_node; + + for_each_node_by_type(np, "pervasive") + if (of_get_parent(np) == be) + map->pmd_regs = of_iomap(np, 0); + + for_each_node_by_type(np, "CBEA-Internal-Interrupt-Controller") + if (of_get_parent(np) == be) + map->iic_regs = of_iomap(np, 2); + for_each_node_by_type(np, "mic-tm") + if (of_get_parent(np) == be) + map->mic_tm_regs = of_iomap(np, 0); + } else { + struct device_node *cpu; /* That hack must die die die ! */ const struct address_prop { unsigned long address; unsigned int len; } __attribute__((packed)) *prop; + cpu = map->cpu_node; + + prop = of_get_property(cpu, "pervasive", NULL); + if (prop != NULL) + map->pmd_regs = ioremap(prop->address, prop->len); + + prop = of_get_property(cpu, "iic", NULL); + if (prop != NULL) + map->iic_regs = ioremap(prop->address, prop->len); + + prop = of_get_property(cpu, "mic-tm", NULL); + if (prop != NULL) + map->mic_tm_regs = ioremap(prop->address, prop->len); + } +} + + +void __init cbe_regs_init(void) +{ + int i; + unsigned int thread_id; + struct device_node *cpu; + + /* Build local fast map of CPUs */ + for_each_possible_cpu(i) { + cbe_thread_map[i].cpu_node = of_get_cpu_node(i, &thread_id); + cbe_thread_map[i].be_node = cbe_get_be_node(i); + cbe_thread_map[i].thread_id = thread_id; + } + + /* Find maps for each device tree CPU */ + for_each_node_by_type(cpu, "cpu") { + struct cbe_regs_map *map; + unsigned int cbe_id; + + cbe_id = cbe_regs_map_count++; + map = &cbe_regs_maps[cbe_id]; if (cbe_regs_map_count > MAX_CBE) { printk(KERN_ERR "cbe_regs: More BE chips than supported" @@ -170,22 +253,21 @@ void __init cbe_regs_init(void) return; } map->cpu_node = cpu; - for_each_possible_cpu(i) - if (cbe_thread_map[i].cpu_node == cpu) - cbe_thread_map[i].regs = map; - prop = get_property(cpu, "pervasive", NULL); - if (prop != NULL) - map->pmd_regs = ioremap(prop->address, prop->len); + for_each_possible_cpu(i) { + struct cbe_thread_map *thread = &cbe_thread_map[i]; - prop = get_property(cpu, "iic", NULL); - if (prop != NULL) - map->iic_regs = ioremap(prop->address, prop->len); + if (thread->cpu_node == cpu) { + thread->regs = map; + thread->cbe_id = cbe_id; + map->be_node = thread->be_node; + cpu_set(i, cbe_local_mask[cbe_id]); + if(thread->thread_id == 0) + cpu_set(i, cbe_first_online_cpu); + } + } - prop = (struct address_prop *)get_property(cpu, "mic-tm", - NULL); - if (prop != NULL) - map->mic_tm_regs = ioremap(prop->address, prop->len); + cbe_fill_regs_map(map); } } diff --git a/arch/powerpc/platforms/cell/cbe_regs.h b/arch/powerpc/platforms/cell/cbe_regs.h index 440a7ec..17d5971 100644 --- a/arch/powerpc/platforms/cell/cbe_regs.h +++ b/arch/powerpc/platforms/cell/cbe_regs.h @@ -255,6 +255,11 @@ struct cbe_mic_tm_regs { extern struct cbe_mic_tm_regs __iomem *cbe_get_mic_tm_regs(struct device_node *np); extern struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu); +/* some utility functions to deal with SMT */ +extern u32 cbe_get_hw_thread_id(int cpu); +extern u32 cbe_cpu_to_node(int cpu); +extern u32 cbe_node_to_cpu(int node); + /* Init this module early */ extern void cbe_regs_init(void); diff --git a/arch/powerpc/platforms/cell/cbe_thermal.c b/arch/powerpc/platforms/cell/cbe_thermal.c index 70e0d96..f370f0f 100644 --- a/arch/powerpc/platforms/cell/cbe_thermal.c +++ b/arch/powerpc/platforms/cell/cbe_thermal.c @@ -1,6 +1,31 @@ /* * thermal support for the cell processor * + * This module adds some sysfs attributes to cpu and spu nodes. + * Base for measurements are the digital thermal sensors (DTS) + * located on the chip. + * The accuracy is 2 degrees, starting from 65 up to 125 degrees celsius + * The attributes can be found under + * /sys/devices/system/cpu/cpuX/thermal + * /sys/devices/system/spu/spuX/thermal + * + * The following attributes are added for each node: + * temperature: + * contains the current temperature measured by the DTS + * throttle_begin: + * throttling begins when temperature is greater or equal to + * throttle_begin. Setting this value to 125 prevents throttling. + * throttle_end: + * throttling is being ceased, if the temperature is lower than + * throttle_end. Due to a delay between applying throttling and + * a reduced temperature this value should be less than throttle_begin. + * A value equal to throttle_begin provides only a very little hysteresis. + * throttle_full_stop: + * If the temperatrue is greater or equal to throttle_full_stop, + * full throttling is applied to the cpu or spu. This value should be + * greater than throttle_begin and throttle_end. Setting this value to + * 65 prevents the unit from running code at all. + * * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 * * Author: Christian Krafft <krafft@de.ibm.com> @@ -31,6 +56,26 @@ #include "cbe_regs.h" #include "spu_priv1_mmio.h" +#define TEMP_MIN 65 +#define TEMP_MAX 125 + +#define SYSDEV_PREFIX_ATTR(_prefix,_name,_mode) \ +struct sysdev_attribute attr_ ## _prefix ## _ ## _name = { \ + .attr = { .name = __stringify(_name), .mode = _mode }, \ + .show = _prefix ## _show_ ## _name, \ + .store = _prefix ## _store_ ## _name, \ +}; + +static inline u8 reg_to_temp(u8 reg_value) +{ + return ((reg_value & 0x3f) << 1) + TEMP_MIN; +} + +static inline u8 temp_to_reg(u8 temp) +{ + return ((temp - TEMP_MIN) >> 1) & 0x3f; +} + static struct cbe_pmd_regs __iomem *get_pmd_regs(struct sys_device *sysdev) { struct spu *spu; @@ -43,14 +88,14 @@ static struct cbe_pmd_regs __iomem *get_pmd_regs(struct sys_device *sysdev) /* returns the value for a given spu in a given register */ static u8 spu_read_register_value(struct sys_device *sysdev, union spe_reg __iomem *reg) { - unsigned int *id; + const unsigned int *id; union spe_reg value; struct spu *spu; /* getting the id from the reg attribute will not work on future device-tree layouts * in future we should store the id to the spu struct and use it here */ spu = container_of(sysdev, struct spu, sysdev); - id = (unsigned int *)get_property(spu_devnode(spu), "reg", NULL); + id = of_get_property(spu_devnode(spu), "reg", NULL); value.val = in_be64(®->val); return value.spe[*id]; @@ -58,20 +103,81 @@ static u8 spu_read_register_value(struct sys_device *sysdev, union spe_reg __iom static ssize_t spu_show_temp(struct sys_device *sysdev, char *buf) { - int value; + u8 value; struct cbe_pmd_regs __iomem *pmd_regs; pmd_regs = get_pmd_regs(sysdev); value = spu_read_register_value(sysdev, &pmd_regs->ts_ctsr1); - /* clear all other bits */ + + return sprintf(buf, "%d\n", reg_to_temp(value)); +} + +static ssize_t show_throttle(struct cbe_pmd_regs __iomem *pmd_regs, char *buf, int pos) +{ + u64 value; + + value = in_be64(&pmd_regs->tm_tpr.val); + /* access the corresponding byte */ + value >>= pos; value &= 0x3F; - /* temp is stored in steps of 2 degrees */ - value *= 2; - /* base temp is 65 degrees */ - value += 65; - return sprintf(buf, "%d\n", (int) value); + return sprintf(buf, "%d\n", reg_to_temp(value)); +} + +static ssize_t store_throttle(struct cbe_pmd_regs __iomem *pmd_regs, const char *buf, size_t size, int pos) +{ + u64 reg_value; + int temp; + u64 new_value; + int ret; + + ret = sscanf(buf, "%u", &temp); + + if (ret != 1 || temp < TEMP_MIN || temp > TEMP_MAX) + return -EINVAL; + + new_value = temp_to_reg(temp); + + reg_value = in_be64(&pmd_regs->tm_tpr.val); + + /* zero out bits for new value */ + reg_value &= ~(0xffull << pos); + /* set bits to new value */ + reg_value |= new_value << pos; + + out_be64(&pmd_regs->tm_tpr.val, reg_value); + return size; +} + +static ssize_t spu_show_throttle_end(struct sys_device *sysdev, char *buf) +{ + return show_throttle(get_pmd_regs(sysdev), buf, 0); +} + +static ssize_t spu_show_throttle_begin(struct sys_device *sysdev, char *buf) +{ + return show_throttle(get_pmd_regs(sysdev), buf, 8); +} + +static ssize_t spu_show_throttle_full_stop(struct sys_device *sysdev, char *buf) +{ + return show_throttle(get_pmd_regs(sysdev), buf, 16); +} + +static ssize_t spu_store_throttle_end(struct sys_device *sysdev, const char *buf, size_t size) +{ + return store_throttle(get_pmd_regs(sysdev), buf, size, 0); +} + +static ssize_t spu_store_throttle_begin(struct sys_device *sysdev, const char *buf, size_t size) +{ + return store_throttle(get_pmd_regs(sysdev), buf, size, 8); +} + +static ssize_t spu_store_throttle_full_stop(struct sys_device *sysdev, const char *buf, size_t size) +{ + return store_throttle(get_pmd_regs(sysdev), buf, size, 16); } static ssize_t ppe_show_temp(struct sys_device *sysdev, char *buf, int pos) @@ -82,16 +188,9 @@ static ssize_t ppe_show_temp(struct sys_device *sysdev, char *buf, int pos) pmd_regs = cbe_get_cpu_pmd_regs(sysdev->id); value = in_be64(&pmd_regs->ts_ctsr2); - /* access the corresponding byte */ - value >>= pos; - /* clear all other bits */ - value &= 0x3F; - /* temp is stored in steps of 2 degrees */ - value *= 2; - /* base temp is 65 degrees */ - value += 65; + value = (value >> pos) & 0x3f; - return sprintf(buf, "%d\n", (int) value); + return sprintf(buf, "%d\n", reg_to_temp(value)); } @@ -108,13 +207,52 @@ static ssize_t ppe_show_temp1(struct sys_device *sysdev, char *buf) return ppe_show_temp(sysdev, buf, 0); } +static ssize_t ppe_show_throttle_end(struct sys_device *sysdev, char *buf) +{ + return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 32); +} + +static ssize_t ppe_show_throttle_begin(struct sys_device *sysdev, char *buf) +{ + return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 40); +} + +static ssize_t ppe_show_throttle_full_stop(struct sys_device *sysdev, char *buf) +{ + return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 48); +} + +static ssize_t ppe_store_throttle_end(struct sys_device *sysdev, const char *buf, size_t size) +{ + return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 32); +} + +static ssize_t ppe_store_throttle_begin(struct sys_device *sysdev, const char *buf, size_t size) +{ + return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 40); +} + +static ssize_t ppe_store_throttle_full_stop(struct sys_device *sysdev, const char *buf, size_t size) +{ + return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 48); +} + + static struct sysdev_attribute attr_spu_temperature = { .attr = {.name = "temperature", .mode = 0400 }, .show = spu_show_temp, }; +static SYSDEV_PREFIX_ATTR(spu, throttle_end, 0600); +static SYSDEV_PREFIX_ATTR(spu, throttle_begin, 0600); +static SYSDEV_PREFIX_ATTR(spu, throttle_full_stop, 0600); + + static struct attribute *spu_attributes[] = { &attr_spu_temperature.attr, + &attr_spu_throttle_end.attr, + &attr_spu_throttle_begin.attr, + &attr_spu_throttle_full_stop.attr, NULL, }; @@ -133,9 +271,16 @@ static struct sysdev_attribute attr_ppe_temperature1 = { .show = ppe_show_temp1, }; +static SYSDEV_PREFIX_ATTR(ppe, throttle_end, 0600); +static SYSDEV_PREFIX_ATTR(ppe, throttle_begin, 0600); +static SYSDEV_PREFIX_ATTR(ppe, throttle_full_stop, 0600); + static struct attribute *ppe_attributes[] = { &attr_ppe_temperature0.attr, &attr_ppe_temperature1.attr, + &attr_ppe_throttle_end.attr, + &attr_ppe_throttle_begin.attr, + &attr_ppe_throttle_full_stop.attr, NULL, }; diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 6666d03..4fc4e927 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c @@ -261,7 +261,7 @@ static int iic_host_xlate(struct irq_host *h, struct device_node *ct, return -ENODEV; if (intsize != 1) return -ENODEV; - val = get_property(ct, "#interrupt-cells", NULL); + val = of_get_property(ct, "#interrupt-cells", NULL); if (val == NULL || *val != 1) return -ENODEV; @@ -327,7 +327,7 @@ static int __init setup_iic(void) if (!device_is_compatible(dn, "IBM,CBEA-Internal-Interrupt-Controller")) continue; - np = get_property(dn, "ibm,interrupt-server-ranges", NULL); + np = of_get_property(dn, "ibm,interrupt-server-ranges", NULL); if (np == NULL) { printk(KERN_WARNING "IIC: CPU association not found\n"); of_node_put(dn); diff --git a/arch/powerpc/platforms/cell/io-workarounds.c b/arch/powerpc/platforms/cell/io-workarounds.c index 7c73128..d68d920 100644 --- a/arch/powerpc/platforms/cell/io-workarounds.c +++ b/arch/powerpc/platforms/cell/io-workarounds.c @@ -318,7 +318,7 @@ static int __init spider_pci_workaround_init(void) */ list_for_each_entry(phb, &hose_list, list_node) { struct device_node *np = phb->arch_data; - const char *model = get_property(np, "model", NULL); + const char *model = of_get_property(np, "model", NULL); /* If no model property or name isn't exactly "pci", skip */ if (model == NULL || strcmp(np->name, "pci")) diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index 67d617b..760caa7 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c @@ -291,9 +291,9 @@ static int cell_iommu_find_ioc(int nid, unsigned long *base) const unsigned int *nidp; const unsigned long *tmp; - nidp = get_property(np, "node-id", NULL); + nidp = of_get_property(np, "node-id", NULL); if (nidp && *nidp == nid) { - tmp = get_property(np, "ioc-translation", NULL); + tmp = of_get_property(np, "ioc-translation", NULL); if (tmp) { *base = *tmp; of_node_put(np); @@ -430,7 +430,7 @@ cell_iommu_setup_window(struct cbe_iommu *iommu, struct device_node *np, struct iommu_window *window; const unsigned int *ioid; - ioid = get_property(np, "ioid", NULL); + ioid = of_get_property(np, "ioid", NULL); if (ioid == NULL) printk(KERN_WARNING "iommu: missing ioid for %s using 0\n", np->full_name); @@ -496,7 +496,7 @@ static void cell_dma_dev_setup(struct device *dev) struct dev_archdata *archdata = &dev->archdata; /* If we run without iommu, no need to do anything */ - if (pci_dma_ops == &dma_direct_ops) + if (get_pci_dma_ops() == &dma_direct_ops) return; /* Current implementation uses the first window available in that @@ -530,7 +530,7 @@ static int cell_of_bus_notify(struct notifier_block *nb, unsigned long action, return 0; /* We use the PCI DMA ops */ - dev->archdata.dma_ops = pci_dma_ops; + dev->archdata.dma_ops = get_pci_dma_ops(); cell_dma_dev_setup(dev); @@ -549,7 +549,7 @@ static int __init cell_iommu_get_window(struct device_node *np, unsigned long index; /* Use ibm,dma-window if available, else, hard code ! */ - dma_window = get_property(np, "ibm,dma-window", NULL); + dma_window = of_get_property(np, "ibm,dma-window", NULL); if (dma_window == NULL) { *base = 0; *size = 0x80000000u; @@ -646,7 +646,7 @@ static int __init cell_iommu_init_disabled(void) unsigned long base = 0, size; /* When no iommu is present, we use direct DMA ops */ - pci_dma_ops = &dma_direct_ops; + set_pci_dma_ops(&dma_direct_ops); /* First make sure all IOC translation is turned off */ cell_disable_iommus(); @@ -734,7 +734,7 @@ static int __init cell_iommu_init(void) } /* Setup default PCI iommu ops */ - pci_dma_ops = &dma_iommu_ops; + set_pci_dma_ops(&dma_iommu_ops); bail: /* Register callbacks on OF platform device addition/removal diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c index 0984c70..3961a08 100644 --- a/arch/powerpc/platforms/cell/ras.c +++ b/arch/powerpc/platforms/cell/ras.c @@ -3,11 +3,13 @@ #include <linux/types.h> #include <linux/kernel.h> #include <linux/smp.h> +#include <linux/reboot.h> #include <asm/reg.h> #include <asm/io.h> #include <asm/prom.h> #include <asm/machdep.h> +#include <asm/rtas.h> #include "ras.h" #include "cbe_regs.h" @@ -82,6 +84,164 @@ static int cbe_machine_check_handler(struct pt_regs *regs) return 0; } +struct ptcal_area { + struct list_head list; + int nid; + int order; + struct page *pages; +}; + +static LIST_HEAD(ptcal_list); + +static int ptcal_start_tok, ptcal_stop_tok; + +static int __init cbe_ptcal_enable_on_node(int nid, int order) +{ + struct ptcal_area *area; + int ret = -ENOMEM; + unsigned long addr; + +#ifdef CONFIG_CRASH_DUMP + rtas_call(ptcal_stop_tok, 1, 1, NULL, nid); +#endif + + area = kmalloc(sizeof(*area), GFP_KERNEL); + if (!area) + goto out_err; + + area->nid = nid; + area->order = order; + area->pages = alloc_pages_node(area->nid, GFP_KERNEL, area->order); + + if (!area->pages) + goto out_free_area; + + addr = __pa(page_address(area->pages)); + + ret = -EIO; + if (rtas_call(ptcal_start_tok, 3, 1, NULL, area->nid, + (unsigned int)(addr >> 32), + (unsigned int)(addr & 0xffffffff))) { + printk(KERN_ERR "%s: error enabling PTCAL on node %d!\n", + __FUNCTION__, nid); + goto out_free_pages; + } + + list_add(&area->list, &ptcal_list); + + return 0; + +out_free_pages: + __free_pages(area->pages, area->order); +out_free_area: + kfree(area); +out_err: + return ret; +} + +static int __init cbe_ptcal_enable(void) +{ + const u32 *size; + struct device_node *np; + int order, found_mic = 0; + + np = of_find_node_by_path("/rtas"); + if (!np) + return -ENODEV; + + size = of_get_property(np, "ibm,cbe-ptcal-size", NULL); + if (!size) + return -ENODEV; + + pr_debug("%s: enabling PTCAL, size = 0x%x\n", __FUNCTION__, *size); + order = get_order(*size); + of_node_put(np); + + /* support for malta device trees, with be@/mic@ nodes */ + for_each_node_by_type(np, "mic-tm") { + cbe_ptcal_enable_on_node(of_node_to_nid(np), order); + found_mic = 1; + } + + if (found_mic) + return 0; + + /* support for older device tree - use cpu nodes */ + for_each_node_by_type(np, "cpu") { + const u32 *nid = of_get_property(np, "node-id", NULL); + if (!nid) { + printk(KERN_ERR "%s: node %s is missing node-id?\n", + __FUNCTION__, np->full_name); + continue; + } + cbe_ptcal_enable_on_node(*nid, order); + found_mic = 1; + } + + return found_mic ? 0 : -ENODEV; +} + +static int cbe_ptcal_disable(void) +{ + struct ptcal_area *area, *tmp; + int ret = 0; + + pr_debug("%s: disabling PTCAL\n", __FUNCTION__); + + list_for_each_entry_safe(area, tmp, &ptcal_list, list) { + /* disable ptcal on this node */ + if (rtas_call(ptcal_stop_tok, 1, 1, NULL, area->nid)) { + printk(KERN_ERR "%s: error disabling PTCAL " + "on node %d!\n", __FUNCTION__, + area->nid); + ret = -EIO; + continue; + } + + /* ensure we can access the PTCAL area */ + memset(page_address(area->pages), 0, + 1 << (area->order + PAGE_SHIFT)); + + /* clean up */ + list_del(&area->list); + __free_pages(area->pages, area->order); + kfree(area); + } + + return ret; +} + +static int cbe_ptcal_notify_reboot(struct notifier_block *nb, + unsigned long code, void *data) +{ + return cbe_ptcal_disable(); +} + +static struct notifier_block cbe_ptcal_reboot_notifier = { + .notifier_call = cbe_ptcal_notify_reboot +}; + +int __init cbe_ptcal_init(void) +{ + int ret; + ptcal_start_tok = rtas_token("ibm,cbe-start-ptcal"); + ptcal_stop_tok = rtas_token("ibm,cbe-stop-ptcal"); + + if (ptcal_start_tok == RTAS_UNKNOWN_SERVICE + || ptcal_stop_tok == RTAS_UNKNOWN_SERVICE) + return -ENODEV; + + ret = register_reboot_notifier(&cbe_ptcal_reboot_notifier); + if (ret) { + printk(KERN_ERR "Can't disable PTCAL, so not enabling\n"); + return ret; + } + + return cbe_ptcal_enable(); +} + +arch_initcall(cbe_ptcal_init); + void __init cbe_ras_init(void) { unsigned long hid0; diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index 36989c2..54b9618 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c @@ -71,7 +71,7 @@ static void cell_show_cpuinfo(struct seq_file *m) root = of_find_node_by_path("/"); if (root) - model = get_property(root, "model", NULL); + model = of_get_property(root, "model", NULL); seq_printf(m, "machine\t\t: CHRP %s\n", model); of_node_put(root); } @@ -190,15 +190,6 @@ static int __init cell_probe(void) return 1; } -/* - * Cell has no legacy IO; anything calling this function has to - * fail or bad things will happen - */ -static int cell_check_legacy_ioport(unsigned int baseport) -{ - return -ENODEV; -} - define_machine(cell) { .name = "Cell", .probe = cell_probe, @@ -211,7 +202,6 @@ define_machine(cell) { .get_rtc_time = rtas_get_rtc_time, .set_rtc_time = rtas_set_rtc_time, .calibrate_decr = generic_calibrate_decr, - .check_legacy_ioport = cell_check_legacy_ioport, .progress = cell_progress, .init_IRQ = cell_init_irq, .pci_setup_phb = rtas_setup_phb, diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c index 21a9ebd..fb1f157 100644 --- a/arch/powerpc/platforms/cell/spider-pic.c +++ b/arch/powerpc/platforms/cell/spider-pic.c @@ -254,25 +254,25 @@ static unsigned int __init spider_find_cascade_and_node(struct spider_pic *pic) } /* Now do the horrible hacks */ - tmp = get_property(pic->of_node, "#interrupt-cells", NULL); + tmp = of_get_property(pic->of_node, "#interrupt-cells", NULL); if (tmp == NULL) return NO_IRQ; intsize = *tmp; - imap = get_property(pic->of_node, "interrupt-map", &imaplen); + imap = of_get_property(pic->of_node, "interrupt-map", &imaplen); if (imap == NULL || imaplen < (intsize + 1)) return NO_IRQ; iic = of_find_node_by_phandle(imap[intsize]); if (iic == NULL) return NO_IRQ; imap += intsize + 1; - tmp = get_property(iic, "#interrupt-cells", NULL); + tmp = of_get_property(iic, "#interrupt-cells", NULL); if (tmp == NULL) return NO_IRQ; intsize = *tmp; /* Assume unit is last entry of interrupt specifier */ unit = imap[intsize - 1]; /* Ok, we have a unit, now let's try to get the node */ - tmp = get_property(iic, "ibm,interrupt-server-ranges", NULL); + tmp = of_get_property(iic, "ibm,interrupt-server-ranges", NULL); if (tmp == NULL) { of_node_put(iic); return NO_IRQ; diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index eba7a26..fec5152 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -36,12 +36,14 @@ #include <asm/xmon.h> const struct spu_management_ops *spu_management_ops; +EXPORT_SYMBOL_GPL(spu_management_ops); + const struct spu_priv1_ops *spu_priv1_ops; static struct list_head spu_list[MAX_NUMNODES]; static LIST_HEAD(spu_full_list); static DEFINE_MUTEX(spu_mutex); -static spinlock_t spu_list_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(spu_list_lock); EXPORT_SYMBOL_GPL(spu_priv1_ops); @@ -290,7 +292,6 @@ spu_irq_class_1(int irq, void *data) return stat ? IRQ_HANDLED : IRQ_NONE; } -EXPORT_SYMBOL_GPL(spu_irq_class_1_bottom); static irqreturn_t spu_irq_class_2(int irq, void *data) @@ -431,10 +432,11 @@ struct spu *spu_alloc_node(int node) spu = list_entry(spu_list[node].next, struct spu, list); list_del_init(&spu->list); pr_debug("Got SPU %d %d\n", spu->number, spu->node); - spu_init_channels(spu); } mutex_unlock(&spu_mutex); + if (spu) + spu_init_channels(spu); return spu; } EXPORT_SYMBOL_GPL(spu_alloc_node); @@ -461,108 +463,6 @@ void spu_free(struct spu *spu) } EXPORT_SYMBOL_GPL(spu_free); -static int spu_handle_mm_fault(struct spu *spu) -{ - struct mm_struct *mm = spu->mm; - struct vm_area_struct *vma; - u64 ea, dsisr, is_write; - int ret; - - ea = spu->dar; - dsisr = spu->dsisr; -#if 0 - if (!IS_VALID_EA(ea)) { - return -EFAULT; - } -#endif /* XXX */ - if (mm == NULL) { - return -EFAULT; - } - if (mm->pgd == NULL) { - return -EFAULT; - } - - down_read(&mm->mmap_sem); - vma = find_vma(mm, ea); - if (!vma) - goto bad_area; - if (vma->vm_start <= ea) - goto good_area; - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; -#if 0 - if (expand_stack(vma, ea)) - goto bad_area; -#endif /* XXX */ -good_area: - is_write = dsisr & MFC_DSISR_ACCESS_PUT; - if (is_write) { - if (!(vma->vm_flags & VM_WRITE)) - goto bad_area; - } else { - if (dsisr & MFC_DSISR_ACCESS_DENIED) - goto bad_area; - if (!(vma->vm_flags & (VM_READ | VM_EXEC))) - goto bad_area; - } - ret = 0; - switch (handle_mm_fault(mm, vma, ea, is_write)) { - case VM_FAULT_MINOR: - current->min_flt++; - break; - case VM_FAULT_MAJOR: - current->maj_flt++; - break; - case VM_FAULT_SIGBUS: - ret = -EFAULT; - goto bad_area; - case VM_FAULT_OOM: - ret = -ENOMEM; - goto bad_area; - default: - BUG(); - } - up_read(&mm->mmap_sem); - return ret; - -bad_area: - up_read(&mm->mmap_sem); - return -EFAULT; -} - -int spu_irq_class_1_bottom(struct spu *spu) -{ - u64 ea, dsisr, access, error = 0UL; - int ret = 0; - - ea = spu->dar; - dsisr = spu->dsisr; - if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)) { - u64 flags; - - access = (_PAGE_PRESENT | _PAGE_USER); - access |= (dsisr & MFC_DSISR_ACCESS_PUT) ? _PAGE_RW : 0UL; - local_irq_save(flags); - if (hash_page(ea, access, 0x300) != 0) - error |= CLASS1_ENABLE_STORAGE_FAULT_INTR; - local_irq_restore(flags); - } - if (error & CLASS1_ENABLE_STORAGE_FAULT_INTR) { - if ((ret = spu_handle_mm_fault(spu)) != 0) - error |= CLASS1_ENABLE_STORAGE_FAULT_INTR; - else - error &= ~CLASS1_ENABLE_STORAGE_FAULT_INTR; - } - spu->dar = 0UL; - spu->dsisr = 0UL; - if (!error) { - spu_restart_dma(spu); - } else { - spu->dma_callback(spu, SPE_EVENT_SPE_DATA_STORAGE); - } - return ret; -} - struct sysdev_class spu_sysdev_class = { set_kset_name("spu") }; @@ -636,12 +536,6 @@ static int spu_create_sysdev(struct spu *spu) return 0; } -static void spu_destroy_sysdev(struct spu *spu) -{ - sysfs_remove_device_from_node(&spu->sysdev, spu->node); - sysdev_unregister(&spu->sysdev); -} - static int __init create_spu(void *data) { struct spu *spu; @@ -693,58 +587,37 @@ out: return ret; } -static void destroy_spu(struct spu *spu) -{ - list_del_init(&spu->list); - list_del_init(&spu->full_list); - - spu_destroy_sysdev(spu); - spu_free_irqs(spu); - spu_destroy_spu(spu); - kfree(spu); -} - -static void cleanup_spu_base(void) -{ - struct spu *spu, *tmp; - int node; - - mutex_lock(&spu_mutex); - for (node = 0; node < MAX_NUMNODES; node++) { - list_for_each_entry_safe(spu, tmp, &spu_list[node], list) - destroy_spu(spu); - } - mutex_unlock(&spu_mutex); - sysdev_class_unregister(&spu_sysdev_class); -} -module_exit(cleanup_spu_base); - static int __init init_spu_base(void) { - int i, ret; + int i, ret = 0; + + for (i = 0; i < MAX_NUMNODES; i++) + INIT_LIST_HEAD(&spu_list[i]); if (!spu_management_ops) - return 0; + goto out; /* create sysdev class for spus */ ret = sysdev_class_register(&spu_sysdev_class); if (ret) - return ret; - - for (i = 0; i < MAX_NUMNODES; i++) - INIT_LIST_HEAD(&spu_list[i]); + goto out; ret = spu_enumerate_spus(create_spu); if (ret) { printk(KERN_WARNING "%s: Error initializing spus\n", __FUNCTION__); - cleanup_spu_base(); - return ret; + goto out_unregister_sysdev_class; } xmon_register_spus(&spu_full_list); + return 0; + + out_unregister_sysdev_class: + sysdev_class_unregister(&spu_sysdev_class); + out: + return ret; } module_init(init_spu_base); diff --git a/arch/powerpc/platforms/cell/spu_coredump.c b/arch/powerpc/platforms/cell/spu_coredump.c index 6915b41..4fd37ff 100644 --- a/arch/powerpc/platforms/cell/spu_coredump.c +++ b/arch/powerpc/platforms/cell/spu_coredump.c @@ -26,19 +26,18 @@ #include <asm/spu.h> -static struct spu_coredump_calls spu_coredump_calls; +static struct spu_coredump_calls *spu_coredump_calls; static DEFINE_MUTEX(spu_coredump_mutex); int arch_notes_size(void) { long ret; - struct module *owner = spu_coredump_calls.owner; ret = -ENOSYS; mutex_lock(&spu_coredump_mutex); - if (owner && try_module_get(owner)) { - ret = spu_coredump_calls.arch_notes_size(); - module_put(owner); + if (spu_coredump_calls && try_module_get(spu_coredump_calls->owner)) { + ret = spu_coredump_calls->arch_notes_size(); + module_put(spu_coredump_calls->owner); } mutex_unlock(&spu_coredump_mutex); return ret; @@ -46,36 +45,35 @@ int arch_notes_size(void) void arch_write_notes(struct file *file) { - struct module *owner = spu_coredump_calls.owner; - mutex_lock(&spu_coredump_mutex); - if (owner && try_module_get(owner)) { - spu_coredump_calls.arch_write_notes(file); - module_put(owner); + if (spu_coredump_calls && try_module_get(spu_coredump_calls->owner)) { + spu_coredump_calls->arch_write_notes(file); + module_put(spu_coredump_calls->owner); } mutex_unlock(&spu_coredump_mutex); } int register_arch_coredump_calls(struct spu_coredump_calls *calls) { - if (spu_coredump_calls.owner) - return -EBUSY; + int ret = 0; + mutex_lock(&spu_coredump_mutex); - spu_coredump_calls.arch_notes_size = calls->arch_notes_size; - spu_coredump_calls.arch_write_notes = calls->arch_write_notes; - spu_coredump_calls.owner = calls->owner; + if (spu_coredump_calls) + ret = -EBUSY; + else + spu_coredump_calls = calls; mutex_unlock(&spu_coredump_mutex); - return 0; + return ret; } EXPORT_SYMBOL_GPL(register_arch_coredump_calls); void unregister_arch_coredump_calls(struct spu_coredump_calls *calls) { - BUG_ON(spu_coredump_calls.owner != calls->owner); + BUG_ON(spu_coredump_calls != calls); mutex_lock(&spu_coredump_mutex); - spu_coredump_calls.owner = NULL; + spu_coredump_calls = NULL; mutex_unlock(&spu_coredump_mutex); } EXPORT_SYMBOL_GPL(unregister_arch_coredump_calls); diff --git a/arch/powerpc/platforms/cell/spu_manage.c b/arch/powerpc/platforms/cell/spu_manage.c index e34599f..1d4562a 100644 --- a/arch/powerpc/platforms/cell/spu_manage.c +++ b/arch/powerpc/platforms/cell/spu_manage.c @@ -48,11 +48,11 @@ static u64 __init find_spu_unit_number(struct device_node *spe) { const unsigned int *prop; int proplen; - prop = get_property(spe, "unit-id", &proplen); + prop = of_get_property(spe, "unit-id", &proplen); if (proplen == 4) return (u64)*prop; - prop = get_property(spe, "reg", &proplen); + prop = of_get_property(spe, "reg", &proplen); if (proplen == 4) return (u64)*prop; @@ -76,12 +76,12 @@ static int __init spu_map_interrupts_old(struct spu *spu, int nid; /* Get the interrupt source unit from the device-tree */ - tmp = get_property(np, "isrc", NULL); + tmp = of_get_property(np, "isrc", NULL); if (!tmp) return -ENODEV; isrc = tmp[0]; - tmp = get_property(np->parent->parent, "node-id", NULL); + tmp = of_get_property(np->parent->parent, "node-id", NULL); if (!tmp) { printk(KERN_WARNING "%s: can't find node-id\n", __FUNCTION__); nid = spu->node; @@ -110,7 +110,7 @@ static void __iomem * __init spu_map_prop_old(struct spu *spu, } __attribute__((packed)) *prop; int proplen; - prop = get_property(n, name, &proplen); + prop = of_get_property(n, name, &proplen); if (prop == NULL || proplen != sizeof (struct address_prop)) return NULL; @@ -124,11 +124,11 @@ static int __init spu_map_device_old(struct spu *spu) int ret; ret = -ENODEV; - spu->name = get_property(node, "name", NULL); + spu->name = of_get_property(node, "name", NULL); if (!spu->name) goto out; - prop = get_property(node, "local-store", NULL); + prop = of_get_property(node, "local-store", NULL); if (!prop) goto out; spu->local_store_phys = *(unsigned long *)prop; @@ -139,7 +139,7 @@ static int __init spu_map_device_old(struct spu *spu) if (!spu->local_store) goto out; - prop = get_property(node, "problem", NULL); + prop = of_get_property(node, "problem", NULL); if (!prop) goto out_unmap; spu->problem_phys = *(unsigned long *)prop; @@ -226,7 +226,7 @@ static int __init spu_map_device(struct spu *spu) struct device_node *np = spu->devnode; int ret = -ENODEV; - spu->name = get_property(np, "name", NULL); + spu->name = of_get_property(np, "name", NULL); if (!spu->name) goto out; diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile index 472217d..2cd89c1 100644 --- a/arch/powerpc/platforms/cell/spufs/Makefile +++ b/arch/powerpc/platforms/cell/spufs/Makefile @@ -1,4 +1,4 @@ -obj-y += switch.o +obj-y += switch.o fault.o obj-$(CONFIG_SPU_FS) += spufs.o spufs-y += inode.o file.o context.o syscalls.o coredump.o diff --git a/arch/powerpc/platforms/cell/spufs/backing_ops.c b/arch/powerpc/platforms/cell/spufs/backing_ops.c index 1898f0d..3322528 100644 --- a/arch/powerpc/platforms/cell/spufs/backing_ops.c +++ b/arch/powerpc/platforms/cell/spufs/backing_ops.c @@ -350,6 +350,11 @@ static int spu_backing_send_mfc_command(struct spu_context *ctx, return ret; } +static void spu_backing_restart_dma(struct spu_context *ctx) +{ + /* nothing to do here */ +} + struct spu_context_ops spu_backing_ops = { .mbox_read = spu_backing_mbox_read, .mbox_stat_read = spu_backing_mbox_stat_read, @@ -376,4 +381,5 @@ struct spu_context_ops spu_backing_ops = { .read_mfc_tagstatus = spu_backing_read_mfc_tagstatus, .get_mfc_free_elements = spu_backing_get_mfc_free_elements, .send_mfc_command = spu_backing_send_mfc_command, + .restart_dma = spu_backing_restart_dma, }; diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c index 04ad2e3..a87d9ca 100644 --- a/arch/powerpc/platforms/cell/spufs/context.c +++ b/arch/powerpc/platforms/cell/spufs/context.c @@ -41,9 +41,10 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang) goto out_free; } spin_lock_init(&ctx->mmio_lock); + spin_lock_init(&ctx->mapping_lock); kref_init(&ctx->kref); mutex_init(&ctx->state_mutex); - init_MUTEX(&ctx->run_sema); + mutex_init(&ctx->run_mutex); init_waitqueue_head(&ctx->ibox_wq); init_waitqueue_head(&ctx->wbox_wq); init_waitqueue_head(&ctx->stop_wq); @@ -51,6 +52,7 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang) ctx->state = SPU_STATE_SAVED; ctx->ops = &spu_backing_ops; ctx->owner = get_task_mm(current); + INIT_LIST_HEAD(&ctx->rq); if (gang) spu_gang_add_ctx(gang, ctx); ctx->rt_priority = current->rt_priority; @@ -75,6 +77,7 @@ void destroy_spu_context(struct kref *kref) spu_fini_csa(&ctx->csa); if (ctx->gang) spu_gang_remove_ctx(ctx->gang, ctx); + BUG_ON(!list_empty(&ctx->rq)); kfree(ctx); } @@ -119,46 +122,6 @@ void spu_unmap_mappings(struct spu_context *ctx) } /** - * spu_acquire_exclusive - lock spu contex and protect against userspace access - * @ctx: spu contex to lock - * - * Note: - * Returns 0 and with the context locked on success - * Returns negative error and with the context _unlocked_ on failure. - */ -int spu_acquire_exclusive(struct spu_context *ctx) -{ - int ret = -EINVAL; - - spu_acquire(ctx); - /* - * Context is about to be freed, so we can't acquire it anymore. - */ - if (!ctx->owner) - goto out_unlock; - - if (ctx->state == SPU_STATE_SAVED) { - ret = spu_activate(ctx, 0); - if (ret) - goto out_unlock; - } else { - /* - * We need to exclude userspace access to the context. - * - * To protect against memory access we invalidate all ptes - * and make sure the pagefault handlers block on the mutex. - */ - spu_unmap_mappings(ctx); - } - - return 0; - - out_unlock: - spu_release(ctx); - return ret; -} - -/** * spu_acquire_runnable - lock spu contex and make sure it is in runnable state * @ctx: spu contex to lock * diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c index 725e195..5d9ad5a 100644 --- a/arch/powerpc/platforms/cell/spufs/coredump.c +++ b/arch/powerpc/platforms/cell/spufs/coredump.c @@ -169,12 +169,12 @@ static void spufs_arch_write_note(struct spufs_ctx_info *ctx_info, int i, struct spu_context *ctx; loff_t pos = 0; int sz, dfd, rc, total = 0; - const int bufsz = 4096; + const int bufsz = PAGE_SIZE; char *name; char fullname[80], *buf; struct elf_note en; - buf = kmalloc(bufsz, GFP_KERNEL); + buf = (void *)get_zeroed_page(GFP_KERNEL); if (!buf) return; @@ -187,9 +187,8 @@ static void spufs_arch_write_note(struct spufs_ctx_info *ctx_info, int i, sz = spufs_coredump_read[i].size; ctx = ctx_info->ctx; - if (!ctx) { - return; - } + if (!ctx) + goto out; sprintf(fullname, "SPU/%d/%s", dfd, name); en.n_namesz = strlen(fullname) + 1; @@ -197,23 +196,25 @@ static void spufs_arch_write_note(struct spufs_ctx_info *ctx_info, int i, en.n_type = NT_SPU; if (!spufs_dump_write(file, &en, sizeof(en))) - return; + goto out; if (!spufs_dump_write(file, fullname, en.n_namesz)) - return; + goto out; if (!spufs_dump_seek(file, roundup((unsigned long)file->f_pos, 4))) - return; + goto out; do { rc = do_coredump_read(i, ctx, buf, bufsz, &pos); if (rc > 0) { if (!spufs_dump_write(file, buf, rc)) - return; + goto out; total += rc; } } while (rc == bufsz && total < sz); spufs_dump_seek(file, roundup((unsigned long)file->f_pos - total + sz, 4)); +out: + free_page((unsigned long)buf); } static void spufs_arch_write_notes(struct file *file) diff --git a/arch/powerpc/platforms/cell/spufs/fault.c b/arch/powerpc/platforms/cell/spufs/fault.c new file mode 100644 index 0000000..0f75c07 --- /dev/null +++ b/arch/powerpc/platforms/cell/spufs/fault.c @@ -0,0 +1,211 @@ +/* + * Low-level SPU handling + * + * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 + * + * Author: Arnd Bergmann <arndb@de.ibm.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <linux/sched.h> +#include <linux/mm.h> +#include <linux/module.h> + +#include <asm/spu.h> +#include <asm/spu_csa.h> + +#include "spufs.h" + +/* + * This ought to be kept in sync with the powerpc specific do_page_fault + * function. Currently, there are a few corner cases that we haven't had + * to handle fortunately. + */ +static int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea, unsigned long dsisr) +{ + struct vm_area_struct *vma; + unsigned long is_write; + int ret; + +#if 0 + if (!IS_VALID_EA(ea)) { + return -EFAULT; + } +#endif /* XXX */ + if (mm == NULL) { + return -EFAULT; + } + if (mm->pgd == NULL) { + return -EFAULT; + } + + down_read(&mm->mmap_sem); + vma = find_vma(mm, ea); + if (!vma) + goto bad_area; + if (vma->vm_start <= ea) + goto good_area; + if (!(vma->vm_flags & VM_GROWSDOWN)) + goto bad_area; + if (expand_stack(vma, ea)) + goto bad_area; +good_area: + is_write = dsisr & MFC_DSISR_ACCESS_PUT; + if (is_write) { + if (!(vma->vm_flags & VM_WRITE)) + goto bad_area; + } else { + if (dsisr & MFC_DSISR_ACCESS_DENIED) + goto bad_area; + if (!(vma->vm_flags & (VM_READ | VM_EXEC))) + goto bad_area; + } + ret = 0; + switch (handle_mm_fault(mm, vma, ea, is_write)) { + case VM_FAULT_MINOR: + current->min_flt++; + break; + case VM_FAULT_MAJOR: + current->maj_flt++; + break; + case VM_FAULT_SIGBUS: + ret = -EFAULT; + goto bad_area; + case VM_FAULT_OOM: + ret = -ENOMEM; + goto bad_area; + default: + BUG(); + } + up_read(&mm->mmap_sem); + return ret; + +bad_area: + up_read(&mm->mmap_sem); + return -EFAULT; +} + +static void spufs_handle_dma_error(struct spu_context *ctx, + unsigned long ea, int type) +{ + if (ctx->flags & SPU_CREATE_EVENTS_ENABLED) { + ctx->event_return |= type; + wake_up_all(&ctx->stop_wq); + } else { + siginfo_t info; + memset(&info, 0, sizeof(info)); + + switch (type) { + case SPE_EVENT_INVALID_DMA: + info.si_signo = SIGBUS; + info.si_code = BUS_OBJERR; + break; + case SPE_EVENT_SPE_DATA_STORAGE: + info.si_signo = SIGBUS; + info.si_addr = (void __user *)ea; + info.si_code = BUS_ADRERR; + break; + case SPE_EVENT_DMA_ALIGNMENT: + info.si_signo = SIGBUS; + /* DAR isn't set for an alignment fault :( */ + info.si_code = BUS_ADRALN; + break; + case SPE_EVENT_SPE_ERROR: + info.si_signo = SIGILL; + info.si_addr = (void __user *)(unsigned long) + ctx->ops->npc_read(ctx) - 4; + info.si_code = ILL_ILLOPC; + break; + } + if (info.si_signo) + force_sig_info(info.si_signo, &info, current); + } +} + +void spufs_dma_callback(struct spu *spu, int type) +{ + spufs_handle_dma_error(spu->ctx, spu->dar, type); +} +EXPORT_SYMBOL_GPL(spufs_dma_callback); + +/* + * bottom half handler for page faults, we can't do this from + * interrupt context, since we might need to sleep. + * we also need to give up the mutex so we can get scheduled + * out while waiting for the backing store. + * + * TODO: try calling hash_page from the interrupt handler first + * in order to speed up the easy case. + */ +int spufs_handle_class1(struct spu_context *ctx) +{ + u64 ea, dsisr, access; + unsigned long flags; + int ret; + + /* + * dar and dsisr get passed from the registers + * to the spu_context, to this function, but not + * back to the spu if it gets scheduled again. + * + * if we don't handle the fault for a saved context + * in time, we can still expect to get the same fault + * the immediately after the context restore. + */ + if (ctx->state == SPU_STATE_RUNNABLE) { + ea = ctx->spu->dar; + dsisr = ctx->spu->dsisr; + ctx->spu->dar= ctx->spu->dsisr = 0; + } else { + ea = ctx->csa.priv1.mfc_dar_RW; + dsisr = ctx->csa.priv1.mfc_dsisr_RW; + ctx->csa.priv1.mfc_dar_RW = 0; + ctx->csa.priv1.mfc_dsisr_RW = 0; + } + + if (!(dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED))) + return 0; + + pr_debug("ctx %p: ea %016lx, dsisr %016lx state %d\n", ctx, ea, + dsisr, ctx->state); + + /* we must not hold the lock when entering spu_handle_mm_fault */ + spu_release(ctx); + + access = (_PAGE_PRESENT | _PAGE_USER); + access |= (dsisr & MFC_DSISR_ACCESS_PUT) ? _PAGE_RW : 0UL; + local_irq_save(flags); + ret = hash_page(ea, access, 0x300); + local_irq_restore(flags); + + /* hashing failed, so try the actual fault handler */ + if (ret) + ret = spu_handle_mm_fault(current->mm, ea, dsisr); + + spu_acquire(ctx); + /* + * If we handled the fault successfully and are in runnable + * state, restart the DMA. + * In case of unhandled error report the problem to user space. + */ + if (!ret) { + if (ctx->spu) + ctx->ops->restart_dma(ctx); + } else + spufs_handle_dma_error(ctx, ea, SPE_EVENT_SPE_DATA_STORAGE); + + return ret; +} +EXPORT_SYMBOL_GPL(spufs_handle_class1); diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 505266a..d010b24 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c @@ -44,9 +44,25 @@ spufs_mem_open(struct inode *inode, struct file *file) { struct spufs_inode_info *i = SPUFS_I(inode); struct spu_context *ctx = i->i_ctx; + + spin_lock(&ctx->mapping_lock); file->private_data = ctx; - ctx->local_store = inode->i_mapping; - smp_wmb(); + if (!i->i_openers++) + ctx->local_store = inode->i_mapping; + spin_unlock(&ctx->mapping_lock); + return 0; +} + +static int +spufs_mem_release(struct inode *inode, struct file *file) +{ + struct spufs_inode_info *i = SPUFS_I(inode); + struct spu_context *ctx = i->i_ctx; + + spin_lock(&ctx->mapping_lock); + if (!--i->i_openers) + ctx->local_store = NULL; + spin_unlock(&ctx->mapping_lock); return 0; } @@ -149,6 +165,7 @@ spufs_mem_mmap(struct file *file, struct vm_area_struct *vma) static const struct file_operations spufs_mem_fops = { .open = spufs_mem_open, + .release = spufs_mem_release, .read = spufs_mem_read, .write = spufs_mem_write, .llseek = generic_file_llseek, @@ -238,16 +255,33 @@ static int spufs_cntl_open(struct inode *inode, struct file *file) struct spufs_inode_info *i = SPUFS_I(inode); struct spu_context *ctx = i->i_ctx; + spin_lock(&ctx->mapping_lock); file->private_data = ctx; - ctx->cntl = inode->i_mapping; - smp_wmb(); + if (!i->i_openers++) + ctx->cntl = inode->i_mapping; + spin_unlock(&ctx->mapping_lock); return simple_attr_open(inode, file, spufs_cntl_get, spufs_cntl_set, "0x%08lx"); } +static int +spufs_cntl_release(struct inode *inode, struct file *file) +{ + struct spufs_inode_info *i = SPUFS_I(inode); + struct spu_context *ctx = i->i_ctx; + + simple_attr_close(inode, file); + + spin_lock(&ctx->mapping_lock); + if (!--i->i_openers) + ctx->cntl = NULL; + spin_unlock(&ctx->mapping_lock); + return 0; +} + static const struct file_operations spufs_cntl_fops = { .open = spufs_cntl_open, - .release = simple_attr_close, + .release = spufs_cntl_release, .read = simple_attr_read, .write = simple_attr_write, .mmap = spufs_cntl_mmap, @@ -723,12 +757,28 @@ static int spufs_signal1_open(struct inode *inode, struct file *file) { struct spufs_inode_info *i = SPUFS_I(inode); struct spu_context *ctx = i->i_ctx; + + spin_lock(&ctx->mapping_lock); file->private_data = ctx; - ctx->signal1 = inode->i_mapping; - smp_wmb(); + if (!i->i_openers++) + ctx->signal1 = inode->i_mapping; + spin_unlock(&ctx->mapping_lock); return nonseekable_open(inode, file); } +static int +spufs_signal1_release(struct inode *inode, struct file *file) +{ + struct spufs_inode_info *i = SPUFS_I(inode); + struct spu_context *ctx = i->i_ctx; + + spin_lock(&ctx->mapping_lock); + if (!--i->i_openers) + ctx->signal1 = NULL; + spin_unlock(&ctx->mapping_lock); + return 0; +} + static ssize_t __spufs_signal1_read(struct spu_context *ctx, char __user *buf, size_t len, loff_t *pos) { @@ -821,6 +871,7 @@ static int spufs_signal1_mmap(struct file *file, struct vm_area_struct *vma) static const struct file_operations spufs_signal1_fops = { .open = spufs_signal1_open, + .release = spufs_signal1_release, .read = spufs_signal1_read, .write = spufs_signal1_write, .mmap = spufs_signal1_mmap, @@ -830,12 +881,28 @@ static int spufs_signal2_open(struct inode *inode, struct file *file) { struct spufs_inode_info *i = SPUFS_I(inode); struct spu_context *ctx = i->i_ctx; + + spin_lock(&ctx->mapping_lock); file->private_data = ctx; - ctx->signal2 = inode->i_mapping; - smp_wmb(); + if (!i->i_openers++) + ctx->signal2 = inode->i_mapping; + spin_unlock(&ctx->mapping_lock); return nonseekable_open(inode, file); } +static int +spufs_signal2_release(struct inode *inode, struct file *file) +{ + struct spufs_inode_info *i = SPUFS_I(inode); + struct spu_context *ctx = i->i_ctx; + + spin_lock(&ctx->mapping_lock); + if (!--i->i_openers) + ctx->signal2 = NULL; + spin_unlock(&ctx->mapping_lock); + return 0; +} + static ssize_t __spufs_signal2_read(struct spu_context *ctx, char __user *buf, size_t len, loff_t *pos) { @@ -932,6 +999,7 @@ static int spufs_signal2_mmap(struct file *file, struct vm_area_struct *vma) static const struct file_operations spufs_signal2_fops = { .open = spufs_signal2_open, + .release = spufs_signal2_release, .read = spufs_signal2_read, .write = spufs_signal2_write, .mmap = spufs_signal2_mmap, @@ -1031,13 +1099,30 @@ static int spufs_mss_open(struct inode *inode, struct file *file) struct spu_context *ctx = i->i_ctx; file->private_data = i->i_ctx; - ctx->mss = inode->i_mapping; - smp_wmb(); + + spin_lock(&ctx->mapping_lock); + if (!i->i_openers++) + ctx->mss = inode->i_mapping; + spin_unlock(&ctx->mapping_lock); return nonseekable_open(inode, file); } +static int +spufs_mss_release(struct inode *inode, struct file *file) +{ + struct spufs_inode_info *i = SPUFS_I(inode); + struct spu_context *ctx = i->i_ctx; + + spin_lock(&ctx->mapping_lock); + if (!--i->i_openers) + ctx->mss = NULL; + spin_unlock(&ctx->mapping_lock); + return 0; +} + static const struct file_operations spufs_mss_fops = { .open = spufs_mss_open, + .release = spufs_mss_release, .mmap = spufs_mss_mmap, }; @@ -1072,14 +1157,30 @@ static int spufs_psmap_open(struct inode *inode, struct file *file) struct spufs_inode_info *i = SPUFS_I(inode); struct spu_context *ctx = i->i_ctx; + spin_lock(&ctx->mapping_lock); file->private_data = i->i_ctx; - ctx->psmap = inode->i_mapping; - smp_wmb(); + if (!i->i_openers++) + ctx->psmap = inode->i_mapping; + spin_unlock(&ctx->mapping_lock); return nonseekable_open(inode, file); } +static int +spufs_psmap_release(struct inode *inode, struct file *file) +{ + struct spufs_inode_info *i = SPUFS_I(inode); + struct spu_context *ctx = i->i_ctx; + + spin_lock(&ctx->mapping_lock); + if (!--i->i_openers) + ctx->psmap = NULL; + spin_unlock(&ctx->mapping_lock); + return 0; +} + static const struct file_operations spufs_psmap_fops = { .open = spufs_psmap_open, + .release = spufs_psmap_release, .mmap = spufs_psmap_mmap, }; @@ -1126,12 +1227,27 @@ static int spufs_mfc_open(struct inode *inode, struct file *file) if (atomic_read(&inode->i_count) != 1) return -EBUSY; + spin_lock(&ctx->mapping_lock); file->private_data = ctx; - ctx->mfc = inode->i_mapping; - smp_wmb(); + if (!i->i_openers++) + ctx->mfc = inode->i_mapping; + spin_unlock(&ctx->mapping_lock); return nonseekable_open(inode, file); } +static int +spufs_mfc_release(struct inode *inode, struct file *file) +{ + struct spufs_inode_info *i = SPUFS_I(inode); + struct spu_context *ctx = i->i_ctx; + + spin_lock(&ctx->mapping_lock); + if (!--i->i_openers) + ctx->mfc = NULL; + spin_unlock(&ctx->mapping_lock); + return 0; +} + /* interrupt-level mfc callback function. */ void spufs_mfc_callback(struct spu *spu) { @@ -1313,7 +1429,10 @@ static ssize_t spufs_mfc_write(struct file *file, const char __user *buffer, if (ret) goto out; - spu_acquire_runnable(ctx, 0); + ret = spu_acquire_runnable(ctx, 0); + if (ret) + goto out; + if (file->f_flags & O_NONBLOCK) { ret = ctx->ops->send_mfc_command(ctx, &cmd); } else { @@ -1399,6 +1518,7 @@ static int spufs_mfc_fasync(int fd, struct file *file, int on) static const struct file_operations spufs_mfc_fops = { .open = spufs_mfc_open, + .release = spufs_mfc_release, .read = spufs_mfc_read, .write = spufs_mfc_write, .poll = spufs_mfc_poll, diff --git a/arch/powerpc/platforms/cell/spufs/hw_ops.c b/arch/powerpc/platforms/cell/spufs/hw_ops.c index ae42e03..428875c 100644 --- a/arch/powerpc/platforms/cell/spufs/hw_ops.c +++ b/arch/powerpc/platforms/cell/spufs/hw_ops.c @@ -296,6 +296,14 @@ static int spu_hw_send_mfc_command(struct spu_context *ctx, } } +static void spu_hw_restart_dma(struct spu_context *ctx) +{ + struct spu_priv2 __iomem *priv2 = ctx->spu->priv2; + + if (!test_bit(SPU_CONTEXT_SWITCH_PENDING, &ctx->spu->flags)) + out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESTART_DMA_COMMAND); +} + struct spu_context_ops spu_hw_ops = { .mbox_read = spu_hw_mbox_read, .mbox_stat_read = spu_hw_mbox_stat_read, @@ -320,4 +328,5 @@ struct spu_context_ops spu_hw_ops = { .read_mfc_tagstatus = spu_hw_read_mfc_tagstatus, .get_mfc_free_elements = spu_hw_get_mfc_free_elements, .send_mfc_command = spu_hw_send_mfc_command, + .restart_dma = spu_hw_restart_dma, }; diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 8079983..13e4f70 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -36,6 +36,7 @@ #include <asm/prom.h> #include <asm/semaphore.h> #include <asm/spu.h> +#include <asm/spu_priv1.h> #include <asm/uaccess.h> #include "spufs.h" @@ -54,6 +55,7 @@ spufs_alloc_inode(struct super_block *sb) ei->i_gang = NULL; ei->i_ctx = NULL; + ei->i_openers = 0; return &ei->vfs_inode; } @@ -520,13 +522,14 @@ out: /* File system initialization */ enum { - Opt_uid, Opt_gid, Opt_err, + Opt_uid, Opt_gid, Opt_mode, Opt_err, }; static match_table_t spufs_tokens = { - { Opt_uid, "uid=%d" }, - { Opt_gid, "gid=%d" }, - { Opt_err, NULL }, + { Opt_uid, "uid=%d" }, + { Opt_gid, "gid=%d" }, + { Opt_mode, "mode=%o" }, + { Opt_err, NULL }, }; static int @@ -553,6 +556,11 @@ spufs_parse_options(char *options, struct inode *root) return 0; root->i_gid = option; break; + case Opt_mode: + if (match_octal(&args[0], &option)) + return 0; + root->i_mode = option | S_IFDIR; + break; default: return 0; } @@ -560,6 +568,11 @@ spufs_parse_options(char *options, struct inode *root) return 1; } +static void spufs_exit_isolated_loader(void) +{ + kfree(isolated_loader); +} + static void spufs_init_isolated_loader(void) { @@ -571,7 +584,7 @@ spufs_init_isolated_loader(void) if (!dn) return; - loader = get_property(dn, "loader", &size); + loader = of_get_property(dn, "loader", &size); if (!loader) return; @@ -653,6 +666,10 @@ static int __init spufs_init(void) { int ret; + ret = -ENODEV; + if (!spu_management_ops) + goto out; + ret = -ENOMEM; spufs_inode_cache = kmem_cache_create("spufs_inode_cache", sizeof(struct spufs_inode_info), 0, @@ -660,25 +677,29 @@ static int __init spufs_init(void) if (!spufs_inode_cache) goto out; - if (spu_sched_init() != 0) { - kmem_cache_destroy(spufs_inode_cache); - goto out; - } - ret = register_filesystem(&spufs_type); + ret = spu_sched_init(); if (ret) goto out_cache; + ret = register_filesystem(&spufs_type); + if (ret) + goto out_sched; ret = register_spu_syscalls(&spufs_calls); if (ret) goto out_fs; ret = register_arch_coredump_calls(&spufs_coredump_calls); if (ret) - goto out_fs; + goto out_syscalls; spufs_init_isolated_loader(); return 0; + +out_syscalls: + unregister_spu_syscalls(&spufs_calls); out_fs: unregister_filesystem(&spufs_type); +out_sched: + spu_sched_exit(); out_cache: kmem_cache_destroy(spufs_inode_cache); out: @@ -689,6 +710,7 @@ module_init(spufs_init); static void __exit spufs_exit(void) { spu_sched_exit(); + spufs_exit_isolated_loader(); unregister_arch_coredump_calls(&spufs_coredump_calls); unregister_spu_syscalls(&spufs_calls); unregister_filesystem(&spufs_type); diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index f95a611..5762660 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c @@ -18,27 +18,6 @@ void spufs_stop_callback(struct spu *spu) wake_up_all(&ctx->stop_wq); } -void spufs_dma_callback(struct spu *spu, int type) -{ - struct spu_context *ctx = spu->ctx; - - if (ctx->flags & SPU_CREATE_EVENTS_ENABLED) { - ctx->event_return |= type; - wake_up_all(&ctx->stop_wq); - } else { - switch (type) { - case SPE_EVENT_DMA_ALIGNMENT: - case SPE_EVENT_SPE_DATA_STORAGE: - case SPE_EVENT_INVALID_DMA: - force_sig(SIGBUS, /* info, */ current); - break; - case SPE_EVENT_SPE_ERROR: - force_sig(SIGILL, /* info */ current); - break; - } - } -} - static inline int spu_stopped(struct spu_context *ctx, u32 * stat) { struct spu *spu; @@ -63,13 +42,18 @@ static int spu_setup_isolated(struct spu_context *ctx) const u32 status_loading = SPU_STATUS_RUNNING | SPU_STATUS_ISOLATED_STATE | SPU_STATUS_ISOLATED_LOAD_STATUS; + ret = -ENODEV; if (!isolated_loader) - return -ENODEV; - - ret = spu_acquire_exclusive(ctx); - if (ret) goto out; + /* + * We need to exclude userspace access to the context. + * + * To protect against memory access we invalidate all ptes + * and make sure the pagefault handlers block on the mutex. + */ + spu_unmap_mappings(ctx); + mfc_cntl = &ctx->spu->priv2->mfc_control_RW; /* purge the MFC DMA queue to ensure no spurious accesses before we @@ -82,7 +66,7 @@ static int spu_setup_isolated(struct spu_context *ctx) printk(KERN_ERR "%s: timeout flushing MFC DMA queue\n", __FUNCTION__); ret = -EIO; - goto out_unlock; + goto out; } cond_resched(); } @@ -119,12 +103,15 @@ static int spu_setup_isolated(struct spu_context *ctx) pr_debug("%s: isolated LOAD failed\n", __FUNCTION__); ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE); ret = -EACCES; + goto out_drop_priv; + } - } else if (!(status & SPU_STATUS_ISOLATED_STATE)) { + if (!(status & SPU_STATUS_ISOLATED_STATE)) { /* This isn't allowed by the CBEA, but check anyway */ pr_debug("%s: SPU fell out of isolated mode?\n", __FUNCTION__); ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_STOP); ret = -EINVAL; + goto out_drop_priv; } out_drop_priv: @@ -132,30 +119,19 @@ out_drop_priv: sr1 |= MFC_STATE1_PROBLEM_STATE_MASK; spu_mfc_sr1_set(ctx->spu, sr1); -out_unlock: - spu_release(ctx); out: return ret; } -static inline int spu_run_init(struct spu_context *ctx, u32 * npc) +static int spu_run_init(struct spu_context *ctx, u32 * npc) { - int ret; - unsigned long runcntl = SPU_RUNCNTL_RUNNABLE; - - ret = spu_acquire_runnable(ctx, 0); - if (ret) - return ret; - if (ctx->flags & SPU_CREATE_ISOLATE) { + unsigned long runcntl; + if (!(ctx->ops->status_read(ctx) & SPU_STATUS_ISOLATED_STATE)) { - /* Need to release ctx, because spu_setup_isolated will - * acquire it exclusively. - */ - spu_release(ctx); - ret = spu_setup_isolated(ctx); - if (!ret) - ret = spu_acquire_runnable(ctx, 0); + int ret = spu_setup_isolated(ctx); + if (ret) + return ret; } /* if userspace has set the runcntrl register (eg, to issue an @@ -164,16 +140,17 @@ static inline int spu_run_init(struct spu_context *ctx, u32 * npc) (SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE); if (runcntl == 0) runcntl = SPU_RUNCNTL_RUNNABLE; + ctx->ops->runcntl_write(ctx, runcntl); } else { spu_start_tick(ctx); ctx->ops->npc_write(ctx, *npc); + ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE); } - ctx->ops->runcntl_write(ctx, runcntl); - return ret; + return 0; } -static inline int spu_run_fini(struct spu_context *ctx, u32 * npc, +static int spu_run_fini(struct spu_context *ctx, u32 * npc, u32 * status) { int ret = 0; @@ -189,19 +166,27 @@ static inline int spu_run_fini(struct spu_context *ctx, u32 * npc, return ret; } -static inline int spu_reacquire_runnable(struct spu_context *ctx, u32 *npc, +static int spu_reacquire_runnable(struct spu_context *ctx, u32 *npc, u32 *status) { int ret; - if ((ret = spu_run_fini(ctx, npc, status)) != 0) + ret = spu_run_fini(ctx, npc, status); + if (ret) return ret; - if (*status & (SPU_STATUS_STOPPED_BY_STOP | - SPU_STATUS_STOPPED_BY_HALT)) { + + if (*status & (SPU_STATUS_STOPPED_BY_STOP | SPU_STATUS_STOPPED_BY_HALT)) return *status; - } - if ((ret = spu_run_init(ctx, npc)) != 0) + + ret = spu_acquire_runnable(ctx, 0); + if (ret) + return ret; + + ret = spu_run_init(ctx, npc); + if (ret) { + spu_release(ctx); return ret; + } return 0; } @@ -253,17 +238,17 @@ int spu_process_callback(struct spu_context *ctx) { struct spu_syscall_block s; u32 ls_pointer, npc; - char *ls; + void __iomem *ls; long spu_ret; int ret; /* get syscall block from local store */ - npc = ctx->ops->npc_read(ctx); - ls = ctx->ops->get_ls(ctx); - ls_pointer = *(u32*)(ls + npc); + npc = ctx->ops->npc_read(ctx) & ~3; + ls = (void __iomem *)ctx->ops->get_ls(ctx); + ls_pointer = in_be32(ls + npc); if (ls_pointer > (LS_SIZE - sizeof(s))) return -EFAULT; - memcpy(&s, ls + ls_pointer, sizeof (s)); + memcpy_fromio(&s, ls + ls_pointer, sizeof(s)); /* do actual syscall without pinning the spu */ ret = 0; @@ -283,7 +268,7 @@ int spu_process_callback(struct spu_context *ctx) } /* write result, jump over indirect pointer */ - memcpy(ls + ls_pointer, &spu_ret, sizeof (spu_ret)); + memcpy_toio(ls + ls_pointer, &spu_ret, sizeof(spu_ret)); ctx->ops->npc_write(ctx, npc); ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE); return ret; @@ -292,11 +277,8 @@ int spu_process_callback(struct spu_context *ctx) static inline int spu_process_events(struct spu_context *ctx) { struct spu *spu = ctx->spu; - u64 pte_fault = MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED; int ret = 0; - if (spu->dsisr & pte_fault) - ret = spu_irq_class_1_bottom(spu); if (spu->class_0_pending) ret = spu_irq_class_0_bottom(spu); if (!ret && signal_pending(current)) @@ -310,14 +292,21 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx, int ret; u32 status; - if (down_interruptible(&ctx->run_sema)) + if (mutex_lock_interruptible(&ctx->run_mutex)) return -ERESTARTSYS; ctx->ops->master_start(ctx); ctx->event_return = 0; - ret = spu_run_init(ctx, npc); + + ret = spu_acquire_runnable(ctx, 0); if (ret) + return ret; + + ret = spu_run_init(ctx, npc); + if (ret) { + spu_release(ctx); goto out; + } do { ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, &status)); @@ -330,6 +319,10 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx, break; status &= ~SPU_STATUS_STOPPED_BY_STOP; } + ret = spufs_handle_class1(ctx); + if (ret) + break; + if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) { ret = spu_reacquire_runnable(ctx, npc, &status); if (ret) { @@ -363,6 +356,6 @@ out2: out: *event = ctx->event_return; - up(&ctx->run_sema); + mutex_unlock(&ctx->run_mutex); return ret; } diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 39823ce..91030b8 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c @@ -71,14 +71,27 @@ static inline int node_allowed(int node) void spu_start_tick(struct spu_context *ctx) { - if (ctx->policy == SCHED_RR) + if (ctx->policy == SCHED_RR) { + /* + * Make sure the exiting bit is cleared. + */ + clear_bit(SPU_SCHED_EXITING, &ctx->sched_flags); + mb(); queue_delayed_work(spu_sched_wq, &ctx->sched_work, SPU_TIMESLICE); + } } void spu_stop_tick(struct spu_context *ctx) { - if (ctx->policy == SCHED_RR) + if (ctx->policy == SCHED_RR) { + /* + * While the work can be rearming normally setting this flag + * makes sure it does not rearm itself anymore. + */ + set_bit(SPU_SCHED_EXITING, &ctx->sched_flags); + mb(); cancel_delayed_work(&ctx->sched_work); + } } void spu_sched_tick(struct work_struct *work) @@ -86,7 +99,15 @@ void spu_sched_tick(struct work_struct *work) struct spu_context *ctx = container_of(work, struct spu_context, sched_work.work); struct spu *spu; - int rearm = 1; + int preempted = 0; + + /* + * If this context is being stopped avoid rescheduling from the + * scheduler tick because we would block on the state_mutex. + * The caller will yield the spu later on anyway. + */ + if (test_bit(SPU_SCHED_EXITING, &ctx->sched_flags)) + return; mutex_lock(&ctx->state_mutex); spu = ctx->spu; @@ -94,12 +115,19 @@ void spu_sched_tick(struct work_struct *work) int best = sched_find_first_bit(spu_prio->bitmap); if (best <= ctx->prio) { spu_deactivate(ctx); - rearm = 0; + preempted = 1; } } mutex_unlock(&ctx->state_mutex); - if (rearm) + if (preempted) { + /* + * We need to break out of the wait loop in spu_run manually + * to ensure this context gets put on the runqueue again + * ASAP. + */ + wake_up(&ctx->stop_wq); + } else spu_start_tick(ctx); } @@ -208,58 +236,40 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx) * spu_add_to_rq - add a context to the runqueue * @ctx: context to add */ -static void spu_add_to_rq(struct spu_context *ctx) +static void __spu_add_to_rq(struct spu_context *ctx) { - spin_lock(&spu_prio->runq_lock); - list_add_tail(&ctx->rq, &spu_prio->runq[ctx->prio]); - set_bit(ctx->prio, spu_prio->bitmap); - spin_unlock(&spu_prio->runq_lock); -} + int prio = ctx->prio; -/** - * spu_del_from_rq - remove a context from the runqueue - * @ctx: context to remove - */ -static void spu_del_from_rq(struct spu_context *ctx) -{ - spin_lock(&spu_prio->runq_lock); - list_del_init(&ctx->rq); - if (list_empty(&spu_prio->runq[ctx->prio])) - clear_bit(ctx->prio, spu_prio->bitmap); - spin_unlock(&spu_prio->runq_lock); + list_add_tail(&ctx->rq, &spu_prio->runq[prio]); + set_bit(prio, spu_prio->bitmap); } -/** - * spu_grab_context - remove one context from the runqueue - * @prio: priority of the context to be removed - * - * This function removes one context from the runqueue for priority @prio. - * If there is more than one context with the given priority the first - * task on the runqueue will be taken. - * - * Returns the spu_context it just removed. - * - * Must be called with spu_prio->runq_lock held. - */ -static struct spu_context *spu_grab_context(int prio) +static void __spu_del_from_rq(struct spu_context *ctx) { - struct list_head *rq = &spu_prio->runq[prio]; + int prio = ctx->prio; - if (list_empty(rq)) - return NULL; - return list_entry(rq->next, struct spu_context, rq); + if (!list_empty(&ctx->rq)) + list_del_init(&ctx->rq); + if (list_empty(&spu_prio->runq[prio])) + clear_bit(prio, spu_prio->bitmap); } static void spu_prio_wait(struct spu_context *ctx) { DEFINE_WAIT(wait); + spin_lock(&spu_prio->runq_lock); prepare_to_wait_exclusive(&ctx->stop_wq, &wait, TASK_INTERRUPTIBLE); if (!signal_pending(current)) { + __spu_add_to_rq(ctx); + spin_unlock(&spu_prio->runq_lock); mutex_unlock(&ctx->state_mutex); schedule(); mutex_lock(&ctx->state_mutex); + spin_lock(&spu_prio->runq_lock); + __spu_del_from_rq(ctx); } + spin_unlock(&spu_prio->runq_lock); __set_current_state(TASK_RUNNING); remove_wait_queue(&ctx->stop_wq, &wait); } @@ -280,9 +290,14 @@ static void spu_reschedule(struct spu *spu) spin_lock(&spu_prio->runq_lock); best = sched_find_first_bit(spu_prio->bitmap); if (best < MAX_PRIO) { - struct spu_context *ctx = spu_grab_context(best); - if (ctx) - wake_up(&ctx->stop_wq); + struct list_head *rq = &spu_prio->runq[best]; + struct spu_context *ctx; + + BUG_ON(list_empty(rq)); + + ctx = list_entry(rq->next, struct spu_context, rq); + __spu_del_from_rq(ctx); + wake_up(&ctx->stop_wq); } spin_unlock(&spu_prio->runq_lock); } @@ -365,6 +380,12 @@ static struct spu *find_victim(struct spu_context *ctx) } spu_unbind_context(spu, victim); mutex_unlock(&victim->state_mutex); + /* + * We need to break out of the wait loop in spu_run + * manually to ensure this context gets put on the + * runqueue again ASAP. + */ + wake_up(&victim->stop_wq); return spu; } } @@ -377,7 +398,7 @@ static struct spu *find_victim(struct spu_context *ctx) * @ctx: spu context to schedule * @flags: flags (currently ignored) * - * Tries to find a free spu to run @ctx. If no free spu is availble + * Tries to find a free spu to run @ctx. If no free spu is available * add the context to the runqueue so it gets woken up once an spu * is available. */ @@ -402,9 +423,7 @@ int spu_activate(struct spu_context *ctx, unsigned long flags) return 0; } - spu_add_to_rq(ctx); spu_prio_wait(ctx); - spu_del_from_rq(ctx); } while (!signal_pending(current)); return -ERESTARTSYS; @@ -438,7 +457,6 @@ void spu_deactivate(struct spu_context *ctx) void spu_yield(struct spu_context *ctx) { struct spu *spu; - int need_yield = 0; if (mutex_trylock(&ctx->state_mutex)) { if ((spu = ctx->spu) != NULL) { @@ -447,13 +465,10 @@ void spu_yield(struct spu_context *ctx) pr_debug("%s: yielding SPU %d NODE %d\n", __FUNCTION__, spu->number, spu->node); spu_deactivate(ctx); - need_yield = 1; } } mutex_unlock(&ctx->state_mutex); } - if (unlikely(need_yield)) - yield(); } int __init spu_sched_init(void) diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index 5c4e47d..0a947fd 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h @@ -41,7 +41,7 @@ struct spu_gang; /* ctx->sched_flags */ enum { - SPU_SCHED_WAKE = 0, /* currently unused */ + SPU_SCHED_EXITING = 0, }; struct spu_context { @@ -50,16 +50,17 @@ struct spu_context { spinlock_t mmio_lock; /* protects mmio access */ struct address_space *local_store; /* local store mapping. */ struct address_space *mfc; /* 'mfc' area mappings. */ - struct address_space *cntl; /* 'control' area mappings. */ - struct address_space *signal1; /* 'signal1' area mappings. */ - struct address_space *signal2; /* 'signal2' area mappings. */ - struct address_space *mss; /* 'mss' area mappings. */ - struct address_space *psmap; /* 'psmap' area mappings. */ + struct address_space *cntl; /* 'control' area mappings. */ + struct address_space *signal1; /* 'signal1' area mappings. */ + struct address_space *signal2; /* 'signal2' area mappings. */ + struct address_space *mss; /* 'mss' area mappings. */ + struct address_space *psmap; /* 'psmap' area mappings. */ + spinlock_t mapping_lock; u64 object_id; /* user space pointer for oprofile */ enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state; struct mutex state_mutex; - struct semaphore run_sema; + struct mutex run_mutex; struct mm_struct *owner; @@ -140,6 +141,7 @@ struct spu_context_ops { struct spu_dma_info * info); void (*proxydma_info_read) (struct spu_context * ctx, struct spu_proxydma_info * info); + void (*restart_dma)(struct spu_context *ctx); }; extern struct spu_context_ops spu_hw_ops; @@ -149,6 +151,7 @@ struct spufs_inode_info { struct spu_context *i_ctx; struct spu_gang *i_gang; struct inode vfs_inode; + int i_openers; }; #define SPUFS_I(inode) \ container_of(inode, struct spufs_inode_info, vfs_inode) @@ -170,6 +173,9 @@ int put_spu_gang(struct spu_gang *gang); void spu_gang_remove_ctx(struct spu_gang *gang, struct spu_context *ctx); void spu_gang_add_ctx(struct spu_gang *gang, struct spu_context *ctx); +/* fault handling */ +int spufs_handle_class1(struct spu_context *ctx); + /* context management */ static inline void spu_acquire(struct spu_context *ctx) { @@ -190,7 +196,6 @@ void spu_unmap_mappings(struct spu_context *ctx); void spu_forget(struct spu_context *ctx); int spu_acquire_runnable(struct spu_context *ctx, unsigned long flags); void spu_acquire_saved(struct spu_context *ctx); -int spu_acquire_exclusive(struct spu_context *ctx); int spu_activate(struct spu_context *ctx, unsigned long flags); void spu_deactivate(struct spu_context *ctx); @@ -218,14 +223,13 @@ extern char *isolated_loader; prepare_to_wait(&(wq), &__wait, TASK_INTERRUPTIBLE); \ if (condition) \ break; \ - if (!signal_pending(current)) { \ - spu_release(ctx); \ - schedule(); \ - spu_acquire(ctx); \ - continue; \ + if (signal_pending(current)) { \ + __ret = -ERESTARTSYS; \ + break; \ } \ - __ret = -ERESTARTSYS; \ - break; \ + spu_release(ctx); \ + schedule(); \ + spu_acquire(ctx); \ } \ finish_wait(&(wq), &__wait); \ __ret; \ diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index fd91c73..8347c4a 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -2084,6 +2084,10 @@ int spu_save(struct spu_state *prev, struct spu *spu) int rc; acquire_spu_lock(spu); /* Step 1. */ + prev->dar = spu->dar; + prev->dsisr = spu->dsisr; + spu->dar = 0; + spu->dsisr = 0; rc = __do_spu_save(prev, spu); /* Steps 2-53. */ release_spu_lock(spu); if (rc != 0 && rc != 2 && rc != 6) { @@ -2109,9 +2113,9 @@ int spu_restore(struct spu_state *new, struct spu *spu) acquire_spu_lock(spu); harvest(NULL, spu); - spu->dar = 0; - spu->dsisr = 0; spu->slb_replace = 0; + new->dar = 0; + new->dsisr = 0; spu->class_0_pending = 0; rc = __do_spu_restore(new, spu); release_spu_lock(spu); diff --git a/arch/powerpc/platforms/celleb/Kconfig b/arch/powerpc/platforms/celleb/Kconfig new file mode 100644 index 0000000..2db1e29 --- /dev/null +++ b/arch/powerpc/platforms/celleb/Kconfig @@ -0,0 +1,9 @@ +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 diff --git a/arch/powerpc/platforms/celleb/iommu.c b/arch/powerpc/platforms/celleb/iommu.c index f63b94c..755d869 100644 --- a/arch/powerpc/platforms/celleb/iommu.c +++ b/arch/powerpc/platforms/celleb/iommu.c @@ -37,7 +37,7 @@ static int __init find_dma_window(u64 *io_space_id, u64 *ioid, const unsigned long *dma_window; for_each_node_by_type(dn, "ioif") { - dma_window = get_property(dn, "toshiba,dma-window", NULL); + dma_window = of_get_property(dn, "toshiba,dma-window", NULL); if (dma_window) { *io_space_id = (dma_window[0] >> 32) & 0xffffffffUL; *ioid = dma_window[0] & 0x7ffUL; @@ -80,7 +80,7 @@ static int celleb_of_bus_notify(struct notifier_block *nb, if (action != BUS_NOTIFY_ADD_DEVICE) return 0; - dev->archdata.dma_ops = pci_dma_ops; + dev->archdata.dma_ops = get_pci_dma_ops(); return 0; } @@ -95,7 +95,7 @@ static int __init celleb_init_iommu(void) return -ENODEV; celleb_init_direct_mapping(); - pci_dma_ops = &dma_direct_ops; + set_pci_dma_ops(&dma_direct_ops); bus_register_notifier(&of_platform_bus_type, &celleb_of_bus_notifier); return 0; diff --git a/arch/powerpc/platforms/celleb/pci.c b/arch/powerpc/platforms/celleb/pci.c index 98de836..d1adf34 100644 --- a/arch/powerpc/platforms/celleb/pci.c +++ b/arch/powerpc/platforms/celleb/pci.c @@ -309,13 +309,13 @@ static int __devinit celleb_setup_fake_pci_device(struct device_node *node, goto error; } - name = get_property(node, "model", &rlen); + name = of_get_property(node, "model", &rlen); if (!name) { printk(KERN_ERR "PCI: model property not found.\n"); goto error; } - wi4 = get_property(node, "reg", &rlen); + wi4 = of_get_property(node, "reg", &rlen); if (wi4 == NULL) goto error; @@ -352,10 +352,10 @@ static int __devinit celleb_setup_fake_pci_device(struct device_node *node, } pr_debug("PCI: res assigned 0x%016lx\n", (unsigned long)*res); - wi0 = get_property(node, "device-id", NULL); - wi1 = get_property(node, "vendor-id", NULL); - wi2 = get_property(node, "class-code", NULL); - wi3 = get_property(node, "revision-id", NULL); + wi0 = of_get_property(node, "device-id", NULL); + wi1 = of_get_property(node, "vendor-id", NULL); + wi2 = of_get_property(node, "class-code", NULL); + wi3 = of_get_property(node, "revision-id", NULL); celleb_config_write_fake(*config, PCI_DEVICE_ID, 2, wi0[0] & 0xffff); celleb_config_write_fake(*config, PCI_VENDOR_ID, 2, wi1[0] & 0xffff); @@ -376,7 +376,7 @@ static int __devinit celleb_setup_fake_pci_device(struct device_node *node, celleb_setup_pci_base_addrs(hose, devno, fn, num_base_addr); - li = get_property(node, "interrupts", &rlen); + li = of_get_property(node, "interrupts", &rlen); val = li[0]; celleb_config_write_fake(*config, PCI_INTERRUPT_PIN, 1, 1); celleb_config_write_fake(*config, PCI_INTERRUPT_LINE, 1, val); @@ -424,7 +424,7 @@ static int __devinit phb_set_bus_ranges(struct device_node *dev, const int *bus_range; unsigned int len; - bus_range = get_property(dev, "bus-range", &len); + bus_range = of_get_property(dev, "bus-range", &len); if (bus_range == NULL || len < 2 * sizeof(int)) return 1; @@ -451,7 +451,7 @@ int __devinit celleb_setup_phb(struct pci_controller *phb) struct device_node *node; unsigned int rlen; - name = get_property(dev, "name", &rlen); + name = of_get_property(dev, "name", &rlen); if (!name) return 1; diff --git a/arch/powerpc/platforms/celleb/setup.c b/arch/powerpc/platforms/celleb/setup.c index 5f4d0d9..596ab2a 100644 --- a/arch/powerpc/platforms/celleb/setup.c +++ b/arch/powerpc/platforms/celleb/setup.c @@ -67,7 +67,7 @@ static void celleb_show_cpuinfo(struct seq_file *m) root = of_find_node_by_path("/"); if (root) - model = get_property(root, "model", NULL); + model = of_get_property(root, "model", NULL); /* using "CHRP" is to trick anaconda into installing FCx into Celleb */ seq_printf(m, "machine\t\t: %s %s\n", celleb_machine_type, model); of_node_put(root); @@ -128,15 +128,6 @@ static int __init celleb_probe(void) return 1; } -/* - * Cell has no legacy IO; anything calling this function has to - * fail or bad things will happen - */ -static int celleb_check_legacy_ioport(unsigned int baseport) -{ - return -ENODEV; -} - #ifdef CONFIG_KEXEC static void celleb_kexec_cpu_down(int crash, int secondary) { @@ -173,7 +164,6 @@ define_machine(celleb) { .get_rtc_time = beat_get_rtc_time, .set_rtc_time = beat_set_rtc_time, .calibrate_decr = generic_calibrate_decr, - .check_legacy_ioport = celleb_check_legacy_ioport, .progress = celleb_progress, .power_save = beat_power_save, .nvram_size = beat_nvram_get_size, diff --git a/arch/powerpc/platforms/chrp/Kconfig b/arch/powerpc/platforms/chrp/Kconfig new file mode 100644 index 0000000..d2c6905 --- /dev/null +++ b/arch/powerpc/platforms/chrp/Kconfig @@ -0,0 +1,11 @@ +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 diff --git a/arch/powerpc/platforms/chrp/nvram.c b/arch/powerpc/platforms/chrp/nvram.c index 0dd4a64..8efd424 100644 --- a/arch/powerpc/platforms/chrp/nvram.c +++ b/arch/powerpc/platforms/chrp/nvram.c @@ -74,7 +74,7 @@ void __init chrp_nvram_init(void) if (nvram == NULL) return; - nbytes_p = get_property(nvram, "#bytes", &proplen); + nbytes_p = of_get_property(nvram, "#bytes", &proplen); if (nbytes_p == NULL || proplen != sizeof(unsigned int)) return; diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c index ddb4a11..1469d64 100644 --- a/arch/powerpc/platforms/chrp/pci.c +++ b/arch/powerpc/platforms/chrp/pci.c @@ -7,7 +7,6 @@ #include <linux/delay.h> #include <linux/string.h> #include <linux/init.h> -#include <linux/ide.h> #include <asm/io.h> #include <asm/pgtable.h> @@ -137,9 +136,11 @@ hydra_init(void) struct device_node *np; struct resource r; - np = find_devices("mac-io"); - if (np == NULL || of_address_to_resource(np, 0, &r)) + np = of_find_node_by_name(NULL, "mac-io"); + if (np == NULL || of_address_to_resource(np, 0, &r)) { + of_node_put(np); return 0; + } Hydra = ioremap(r.start, r.end-r.start); printk("Hydra Mac I/O at %llx\n", (unsigned long long)r.start); printk("Hydra Feature_Control was %x", @@ -186,10 +187,9 @@ setup_python(struct pci_controller *hose, struct device_node *dev) /* Marvell Discovery II based Pegasos 2 */ static void __init setup_peg2(struct pci_controller *hose, struct device_node *dev) { - struct device_node *root = find_path_device("/"); + struct device_node *root = of_find_node_by_path("/"); struct device_node *rtas; - of_node_get(root); rtas = of_find_node_by_name (root, "rtas"); if (rtas) { hose->ops = &rtas_pci_ops; @@ -199,6 +199,7 @@ static void __init setup_peg2(struct pci_controller *hose, struct device_node *d " your firmware\n"); } pci_assign_all_buses = 1; + /* keep the reference to the root node */ } void __init @@ -211,14 +212,14 @@ chrp_find_bridges(void) const unsigned int *dma; const char *model, *machine; int is_longtrail = 0, is_mot = 0, is_pegasos = 0; - struct device_node *root = find_path_device("/"); + struct device_node *root = of_find_node_by_path("/"); struct resource r; /* * The PCI host bridge nodes on some machines don't have * properties to adequately identify them, so we have to * look at what sort of machine this is as well. */ - machine = get_property(root, "model", NULL); + machine = of_get_property(root, "model", NULL); if (machine != NULL) { is_longtrail = strncmp(machine, "IBM,LongTrail", 13) == 0; is_mot = strncmp(machine, "MOT", 3) == 0; @@ -237,7 +238,7 @@ chrp_find_bridges(void) dev->full_name); continue; } - 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)) { printk(KERN_WARNING "Can't get bus-range for %s\n", dev->full_name); @@ -263,7 +264,7 @@ chrp_find_bridges(void) hose->first_busno = bus_range[0]; hose->last_busno = bus_range[1]; - model = get_property(dev, "model", NULL); + model = of_get_property(dev, "model", NULL); if (model == NULL) model = "<none>"; if (device_is_compatible(dev, "IBM,python")) { @@ -285,7 +286,8 @@ chrp_find_bridges(void) r.start + 0x000f8000, r.start + 0x000f8010); if (index == 0) { - dma = get_property(dev, "system-dma-base",&len); + dma = of_get_property(dev, "system-dma-base", + &len); if (dma && len >= sizeof(*dma)) { dma = (unsigned int *) (((unsigned long)dma) + @@ -303,12 +305,13 @@ chrp_find_bridges(void) /* check the first bridge for a property that we can use to set pci_dram_offset */ - dma = get_property(dev, "ibm,dma-ranges", &len); + dma = of_get_property(dev, "ibm,dma-ranges", &len); if (index == 0 && dma != NULL && len >= 6 * sizeof(*dma)) { pci_dram_offset = dma[2] - dma[3]; printk("pci_dram_offset = %lx\n", pci_dram_offset); } } + of_node_put(root); } /* SL82C105 IDE Control/Status Register */ diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 117c9a0..1870038 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c @@ -28,7 +28,6 @@ #include <linux/adb.h> #include <linux/module.h> #include <linux/delay.h> -#include <linux/ide.h> #include <linux/console.h> #include <linux/seq_file.h> #include <linux/root_dev.h> @@ -111,9 +110,9 @@ void chrp_show_cpuinfo(struct seq_file *m) struct device_node *root; const char *model = ""; - root = find_path_device("/"); + root = of_find_node_by_path("/"); if (root) - model = get_property(root, "model", NULL); + model = of_get_property(root, "model", NULL); seq_printf(m, "machine\t\t: CHRP %s\n", model); /* longtrail (goldengate) stuff */ @@ -161,6 +160,7 @@ void chrp_show_cpuinfo(struct seq_file *m) gg2_cachetypes[(t>>2) & 3], gg2_cachemodes[t & 3]); } + of_node_put(root); } /* @@ -205,13 +205,15 @@ static void __init sio_init(void) { struct device_node *root; - if ((root = find_path_device("/")) && - !strncmp(get_property(root, "model", NULL), "IBM,LongTrail", 13)) { + if ((root = of_find_node_by_path("/")) && + !strncmp(of_get_property(root, "model", NULL), + "IBM,LongTrail", 13)) { /* logical device 0 (KBC/Keyboard) */ sio_fixup_irq("keyboard", 0, 1, 2); /* select logical device 1 (KBC/Mouse) */ sio_fixup_irq("mouse", 1, 12, 2); } + of_node_put(root); } @@ -224,12 +226,12 @@ static void __init pegasos_set_l2cr(void) return; /* Enable L2 cache if needed */ - np = find_type_devices("cpu"); + np = of_find_node_by_type(NULL, "cpu"); if (np != NULL) { - const unsigned int *l2cr = get_property(np, "l2cr", NULL); + const unsigned int *l2cr = of_get_property(np, "l2cr", NULL); if (l2cr == NULL) { printk ("Pegasos l2cr : no cpu l2cr property found\n"); - return; + goto out; } if (!((*l2cr) & 0x80000000)) { printk ("Pegasos l2cr : L2 cache was not active, " @@ -238,6 +240,8 @@ static void __init pegasos_set_l2cr(void) _set_L2CR((*l2cr) | 0x80000000); } } +out: + of_node_put(np); } static void briq_restart(char *cmd) @@ -250,14 +254,14 @@ static void briq_restart(char *cmd) void __init chrp_setup_arch(void) { - struct device_node *root = find_path_device ("/"); + struct device_node *root = of_find_node_by_path("/"); const char *machine = NULL; /* init to some ~sane value until calibrate_delay() runs */ loops_per_jiffy = 50000000/HZ; if (root) - machine = get_property(root, "model", NULL); + machine = of_get_property(root, "model", NULL); if (machine && strncmp(machine, "Pegasos", 7) == 0) { _chrp_type = _CHRP_Pegasos; } else if (machine && strncmp(machine, "IBM", 3) == 0) { @@ -273,6 +277,7 @@ void __init chrp_setup_arch(void) /* Let's assume it is an IBM chrp if all else fails */ _chrp_type = _CHRP_IBM; } + of_node_put(root); printk("chrp type = %x [%s]\n", _chrp_type, chrp_names[_chrp_type]); rtas_initialize(); @@ -361,8 +366,8 @@ static void __init chrp_find_openpic(void) return; root = of_find_node_by_path("/"); if (root) { - opprop = get_property(root, "platform-open-pic", &oplen); - na = prom_n_addr_cells(root); + opprop = of_get_property(root, "platform-open-pic", &oplen); + na = of_n_addr_cells(root); } if (opprop && oplen >= na * sizeof(unsigned int)) { opaddr = opprop[na-1]; /* assume 32-bit */ @@ -378,7 +383,7 @@ static void __init chrp_find_openpic(void) printk(KERN_INFO "OpenPIC at %lx\n", opaddr); - iranges = get_property(np, "interrupt-ranges", &len); + iranges = of_get_property(np, "interrupt-ranges", &len); if (iranges == NULL) len = 0; /* non-distributed mpic */ else @@ -427,7 +432,7 @@ static void __init chrp_find_openpic(void) of_node_put(np); } -#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON) +#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_XMON) static struct irqaction xmon_irqaction = { .handler = xmon_irq, .mask = CPU_MASK_NONE, @@ -463,15 +468,16 @@ static void __init chrp_find_8259(void) * Also, Pegasos-type platforms don't have a proper node to start * from anyway */ - for (np = find_devices("pci"); np != NULL; np = np->next) { - const unsigned int *addrp = get_property(np, + for_each_node_by_name(np, "pci") { + const unsigned int *addrp = of_get_property(np, "8259-interrupt-acknowledge", NULL); if (addrp == NULL) continue; - chrp_int_ack = addrp[prom_n_addr_cells(np)-1]; + chrp_int_ack = addrp[of_n_addr_cells(np)-1]; break; } + of_node_put(np); if (np == NULL) printk(KERN_WARNING "Cannot find PCI interrupt acknowledge" " address, polling\n"); @@ -493,7 +499,7 @@ static void __init chrp_find_8259(void) void __init chrp_init_IRQ(void) { -#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON) +#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_XMON) struct device_node *kbd; #endif chrp_find_openpic(); @@ -510,13 +516,14 @@ void __init chrp_init_IRQ(void) if (_chrp_type == _CHRP_Pegasos) ppc_md.get_irq = i8259_irq; -#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON) +#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_XMON) /* see if there is a keyboard in the device tree with a parent of type "adb" */ - for (kbd = find_devices("keyboard"); kbd; kbd = kbd->next) + for_each_node_by_name(kbd, "keyboard") if (kbd->parent && kbd->parent->type && strcmp(kbd->parent->type, "adb") == 0) break; + of_node_put(kbd); if (kbd) setup_irq(HYDRA_INT_ADB_NMI, &xmon_irqaction); #endif @@ -542,9 +549,9 @@ chrp_init2(void) /* Get the event scan rate for the rtas so we know how * often it expects a heartbeat. -- Cort */ - device = find_devices("rtas"); + device = of_find_node_by_name(NULL, "rtas"); if (device) - p = get_property(device, "rtas-event-scan-rate", NULL); + p = of_get_property(device, "rtas-event-scan-rate", NULL); if (p && *p) { /* * Arrange to call chrp_event_scan at least *p times @@ -571,6 +578,7 @@ chrp_init2(void) printk("RTAS Event Scan Rate: %u (%lu jiffies)\n", *p, interval); } + of_node_put(device); if (ppc_md.progress) ppc_md.progress(" Have fun! ", 0x7777); diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c index 7d78890..96d1e4b 100644 --- a/arch/powerpc/platforms/chrp/time.c +++ b/arch/powerpc/platforms/chrp/time.c @@ -39,12 +39,17 @@ long __init chrp_time_init(void) struct resource r; int base; - rtcs = find_compatible_devices("rtc", "pnpPNP,b00"); + rtcs = of_find_compatible_node(NULL, "rtc", "pnpPNP,b00"); if (rtcs == NULL) - rtcs = find_compatible_devices("rtc", "ds1385-rtc"); - if (rtcs == NULL || of_address_to_resource(rtcs, 0, &r)) + rtcs = of_find_compatible_node(NULL, "rtc", "ds1385-rtc"); + if (rtcs == NULL) + return 0; + if (of_address_to_resource(rtcs, 0, &r)) { + of_node_put(rtcs); return 0; - + } + of_node_put(rtcs); + base = r.start; nvram_as1 = 0; nvram_as0 = base; diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig index 3410bcb..9557908 100644 --- a/arch/powerpc/platforms/embedded6xx/Kconfig +++ b/arch/powerpc/platforms/embedded6xx/Kconfig @@ -2,78 +2,6 @@ choice prompt "Machine Type" depends on EMBEDDED6xx -config KATANA - bool "Artesyn-Katana" - help - Select KATANA if configuring an Artesyn KATANA 750i or 3750 - cPCI board. - -config WILLOW - bool "Cogent-Willow" - -config CPCI690 - bool "Force-CPCI690" - help - Select CPCI690 if configuring a Force CPCI690 cPCI board. - -config POWERPMC250 - bool "Force-PowerPMC250" - -config CHESTNUT - bool "IBM 750FX Eval board or 750GX Eval board" - help - Select CHESTNUT if configuring an IBM 750FX Eval Board or a - IBM 750GX Eval board. - -config SPRUCE - bool "IBM-Spruce" - select PPC_INDIRECT_PCI - -config HDPU - bool "Sky-HDPU" - help - Select HDPU if configuring a Sky Computers Compute Blade. - -config HDPU_FEATURES - depends on HDPU - tristate "HDPU-Features" - help - Select to enable HDPU enhanced features. - -config EV64260 - bool "Marvell-EV64260BP" - help - Select EV64260 if configuring a Marvell (formerly Galileo) - EV64260BP Evaluation platform. - -config LOPEC - bool "Motorola-LoPEC" - select PPC_I8259 - -config MVME5100 - bool "Motorola-MVME5100" - select PPC_INDIRECT_PCI - -config PPLUS - bool "Motorola-PowerPlus" - select PPC_I8259 - select PPC_INDIRECT_PCI - -config PRPMC750 - bool "Motorola-PrPMC750" - select PPC_INDIRECT_PCI - -config PRPMC800 - bool "Motorola-PrPMC800" - select PPC_INDIRECT_PCI - -config SANDPOINT - bool "Motorola-Sandpoint" - select PPC_I8259 - help - Select SANDPOINT if configuring for a Motorola Sandpoint X3 - (any flavor). - config LINKSTATION bool "Linkstation / Kurobox(HG) from Buffalo" select MPIC @@ -97,212 +25,24 @@ config MPC7448HPC2 help Select MPC7448HPC2 if configuring for Freescale MPC7448HPC2 (Taiga) platform - -config RADSTONE_PPC7D - bool "Radstone Technology PPC7D board" - select PPC_I8259 - -config PAL4 - bool "SBS-Palomar4" - -config EST8260 - bool "EST8260" - ---help--- - The EST8260 is a single-board computer manufactured by Wind River - Systems, Inc. (formerly Embedded Support Tools Corp.) and based on - the MPC8260. Wind River Systems has a website at - <http://www.windriver.com/>, but the EST8260 cannot be found on it - and has probably been discontinued or rebadged. - -config SBC82xx - bool "SBC82xx" - ---help--- - SBC PowerQUICC II, single-board computer with MPC82xx CPU - Manufacturer: Wind River Systems, Inc. - Date of Release: May 2003 - End of Life: - - URL: <http://www.windriver.com/> - -config SBS8260 - bool "SBS8260" - -config RPX8260 - bool "RPXSUPER" - -config TQM8260 - bool "TQM8260" - ---help--- - MPC8260 based module, little larger than credit card, - up to 128 MB global + 64 MB local RAM, 32 MB Flash, - 32 kB EEPROM, 256 kB L@ Cache, 10baseT + 100baseT Ethernet, - 2 x serial ports, ... - Manufacturer: TQ Components, www.tq-group.de - Date of Release: June 2001 - End of Life: not yet :-) - URL: <http://www.denx.de/PDF/TQM82xx_SPEC_Rev005.pdf> - -config ADS8272 - bool "ADS8272" - -config PQ2FADS - bool "Freescale-PQ2FADS" - help - Select PQ2FADS if you wish to configure for a Freescale - PQ2FADS board (-VR or -ZU). - -config EV64360 - bool "Marvell-EV64360BP" - help - Select EV64360 if configuring a Marvell EV64360BP Evaluation - platform. endchoice -config PQ2ADS - bool - depends on ADS8272 - default y - -config TQM8xxL - bool - depends on 8xx && (TQM823L || TQM850L || FPS850L || TQM855L || TQM860L) - default y - -config 8260 - bool "CPM2 Support" if WILLOW - depends on 6xx - default y if TQM8260 || RPX8260 || EST8260 || SBS8260 || SBC82xx || PQ2FADS - help - The MPC8260 is a typical embedded CPU made by Motorola. Selecting - this option means that you wish to build a kernel for a machine with - an 8260 class CPU. - -config 8272 - bool - depends on 6xx - default y if ADS8272 - select 8260 - help - The MPC8272 CPM has a different internal dpram setup than other CPM2 - devices - -config CPM2 - bool - depends on 8260 || MPC8560 || MPC8555 - default y - help - The CPM2 (Communications Processor Module) is a coprocessor on - embedded CPUs made by Motorola. Selecting this option means that - you wish to build a kernel for a machine with a CPM2 coprocessor - on it (826x, 827x, 8560). - -config PPC_GEN550 - bool - depends on SANDPOINT || SPRUCE || PPLUS || \ - PRPMC750 || PRPMC800 || LOPEC || \ - (EV64260 && !SERIAL_MPSC) || CHESTNUT || RADSTONE_PPC7D || \ - 83xx || LINKSTATION - default y - -config FORCE - bool - depends on 6xx && POWERPMC250 - default y - -config GT64260 - bool - depends on EV64260 || CPCI690 - default y - -config MV64360 # Really MV64360 & MV64460 - bool - depends on CHESTNUT || KATANA || RADSTONE_PPC7D || HDPU || EV64360 - default y - -config MV64X60 - bool - depends on (GT64260 || MV64360) - select PPC_INDIRECT_PCI - default y - config TSI108_BRIDGE bool depends on MPC7448HPC2 default y -menu "Set bridge options" - depends on MV64X60 - -config NOT_COHERENT_CACHE - bool "Turn off Cache Coherency" - default n - help - Some 64x60 bridges lock up when trying to enforce cache coherency. - When this option is selected, cache coherency will be turned off. - Note that this can cause other problems (e.g., stale data being - speculatively loaded via a cached mapping). Use at your own risk. - -config MV64X60_BASE - hex "Set bridge base used by firmware" - default "0xf1000000" - help - A firmware can leave the base address of the bridge's registers at - a non-standard location. If so, set this value to reflect the - address of that non-standard location. - -config MV64X60_NEW_BASE - hex "Set bridge base used by kernel" - default "0xf1000000" - help - If the current base address of the bridge's registers is not where - you want it, set this value to the address that you want it moved to. - -endmenu - -config NONMONARCH_SUPPORT - bool "Enable Non-Monarch Support" - depends on PRPMC800 - -config HARRIER - bool - depends on PRPMC800 - default y - -config EPIC_SERIAL_MODE - bool - depends on 6xx && (LOPEC || SANDPOINT) - default y - config MPC10X_BRIDGE bool - depends on POWERPMC250 || LOPEC || SANDPOINT || LINKSTATION + depends on LINKSTATION select PPC_INDIRECT_PCI default y config MPC10X_OPENPIC bool - depends on POWERPMC250 || LOPEC || SANDPOINT || LINKSTATION + depends on LINKSTATION default y config MPC10X_STORE_GATHERING bool "Enable MPC10x store gathering" depends on MPC10X_BRIDGE - -config SANDPOINT_ENABLE_UART1 - bool "Enable DUART mode on Sandpoint" - depends on SANDPOINT - help - If this option is enabled then the MPC824x processor will run - in DUART mode instead of UART mode. - -config HARRIER_STORE_GATHERING - bool "Enable Harrier store gathering" - depends on HARRIER - -config MVME5100_IPMC761_PRESENT - bool "MVME5100 configured with an IPMC761" - depends on MVME5100 - select PPC_I8259 - -config SPRUCE_BAUD_33M - bool "Spruce baud clock support" - depends on SPRUCE diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c index 3f6c411..b412f00 100644 --- a/arch/powerpc/platforms/embedded6xx/linkstation.c +++ b/arch/powerpc/platforms/embedded6xx/linkstation.c @@ -58,11 +58,11 @@ static int __init add_bridge(struct device_node *dev) { int len; struct pci_controller *hose; - int *bus_range; + const int *bus_range; printk("Adding PCI host bridge %s\n", dev->full_name); - bus_range = (int *) get_property(dev, "bus-range", &len); + bus_range = of_get_property(dev, "bus-range", &len); if (bus_range == NULL || len < 2 * sizeof(int)) printk(KERN_WARNING "Can't get bus-range for %s, assume" " bus 0\n", dev->full_name); @@ -106,7 +106,7 @@ static void __init linkstation_init_IRQ(void) { struct mpic *mpic; struct device_node *dnp; - void *prop; + const u32 *prop; int size; phys_addr_t paddr; @@ -114,7 +114,7 @@ static void __init linkstation_init_IRQ(void) if (dnp == NULL) return; - prop = (struct device_node *)get_property(dnp, "reg", &size); + prop = of_get_property(dnp, "reg", &size); paddr = (phys_addr_t)of_translate_address(dnp, prop); mpic = mpic_alloc(dnp, paddr, MPIC_PRIMARY | MPIC_WANTS_RESET, 4, 32, " EPIC "); diff --git a/arch/powerpc/platforms/embedded6xx/ls_uart.c b/arch/powerpc/platforms/embedded6xx/ls_uart.c index 0e83776..d0bee9f 100644 --- a/arch/powerpc/platforms/embedded6xx/ls_uart.c +++ b/arch/powerpc/platforms/embedded6xx/ls_uart.c @@ -110,8 +110,8 @@ static int __init ls_uarts_init(void) if (!avr) return -EINVAL; - avr_clock = *(u32*)get_property(avr, "clock-frequency", &len); - phys_addr = ((u32*)get_property(avr, "reg", &len))[0]; + avr_clock = *(u32*)of_get_property(avr, "clock-frequency", &len); + phys_addr = ((u32*)of_get_property(avr, "reg", &len))[0]; if (!avr_clock || !phys_addr) return -EINVAL; diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c index 3fcc85f..c3f64dd 100644 --- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c +++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c @@ -25,7 +25,6 @@ #include <linux/console.h> #include <linux/delay.h> #include <linux/irq.h> -#include <linux/ide.h> #include <linux/seq_file.h> #include <linux/root_dev.h> #include <linux/serial.h> @@ -82,7 +81,7 @@ static void __init mpc7448_hpc2_setup_arch(void) if (cpu != 0) { const unsigned int *fp; - fp = get_property(cpu, "clock-frequency", NULL); + fp = of_get_property(cpu, "clock-frequency", NULL); if (fp != 0) loops_per_jiffy = *fp / HZ; else @@ -91,16 +90,6 @@ static void __init mpc7448_hpc2_setup_arch(void) } tsi108_csr_vir_base = get_vir_csrbase(); -#ifdef CONFIG_ROOT_NFS - ROOT_DEV = Root_NFS; -#else - ROOT_DEV = Root_HDA1; -#endif - -#ifdef CONFIG_BLK_DEV_INITRD - ROOT_DEV = Root_RAM0; -#endif - /* setup PCI host bridge */ #ifdef CONFIG_PCI for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) @@ -143,7 +132,7 @@ static void __init mpc7448_hpc2_init_IRQ(void) tsi_pic = of_find_node_by_type(NULL, "open-pic"); if (tsi_pic) { unsigned int size; - const void *prop = get_property(tsi_pic, "reg", &size); + const void *prop = of_get_property(tsi_pic, "reg", &size); mpic_paddr = of_translate_address(tsi_pic, prop); } diff --git a/arch/powerpc/platforms/iseries/Kconfig b/arch/powerpc/platforms/iseries/Kconfig index 54e6b3b..46c3a8e 100644 --- a/arch/powerpc/platforms/iseries/Kconfig +++ b/arch/powerpc/platforms/iseries/Kconfig @@ -1,3 +1,7 @@ +config PPC_ISERIES + bool "IBM Legacy iSeries" + depends on PPC_MULTIPLATFORM && PPC64 + select PPC_INDIRECT_IO menu "iSeries device drivers" depends on PPC_ISERIES diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index d7a756d..3b6a966 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c @@ -171,7 +171,7 @@ void iommu_devnode_init_iSeries(struct pci_dev *pdev, struct device_node *dn) { struct iommu_table *tbl; struct pci_dn *pdn = PCI_DN(dn); - const u32 *lsn = get_property(dn, "linux,logical-slot-number", NULL); + const u32 *lsn = of_get_property(dn, "linux,logical-slot-number", NULL); BUG_ON(lsn == NULL); @@ -194,5 +194,5 @@ void iommu_init_early_iSeries(void) ppc_md.tce_build = tce_build_iSeries; ppc_md.tce_free = tce_free_iSeries; - pci_dma_ops = &dma_iommu_ops; + set_pci_dma_ops(&dma_iommu_ops); } diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c index 5225abf..63b3367 100644 --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c @@ -30,7 +30,6 @@ #include <linux/param.h> #include <linux/string.h> #include <linux/bootmem.h> -#include <linux/ide.h> #include <linux/irq.h> #include <linux/spinlock.h> @@ -337,6 +336,8 @@ unsigned int iSeries_get_irq(void) return irq; } +#ifdef CONFIG_PCI + static int iseries_irq_host_map(struct irq_host *h, unsigned int virq, irq_hw_number_t hw) { @@ -384,3 +385,4 @@ void __init iSeries_init_IRQ(void) "failed with rc 0x%x\n", ret); } +#endif /* CONFIG_PCI */ diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index 4a06d9c..9c97422 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -24,7 +24,6 @@ #include <linux/string.h> #include <linux/init.h> #include <linux/module.h> -#include <linux/ide.h> #include <linux/pci.h> #include <asm/io.h> @@ -177,7 +176,7 @@ void __init iSeries_pci_final_fixup(void) struct pci_dn *pdn = PCI_DN(node); const u32 *agent; - agent = get_property(node, "linux,agent-id", NULL); + agent = of_get_property(node, "linux,agent-id", NULL); if ((pdn != NULL) && (agent != NULL)) { u8 irq = iSeries_allocate_IRQ(pdn->busno, 0, pdn->bussubno); @@ -755,7 +754,7 @@ void __init iSeries_pcibios_init(void) if ((node->type == NULL) || (strcmp(node->type, "pci") != 0)) continue; - busp = get_property(node, "bus-range", NULL); + busp = of_get_property(node, "bus-range", NULL); if (busp == NULL) continue; bus = *busp; diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index cce7e30..7f5dcee 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -628,15 +628,6 @@ static void iseries_iounmap(volatile void __iomem *token) { } -/* - * iSeries has no legacy IO, anything calling this function has to - * fail or bad things will happen - */ -static int iseries_check_legacy_ioport(unsigned int baseport) -{ - return -ENODEV; -} - static int __init iseries_probe(void) { unsigned long root = of_get_flat_dt_root(); @@ -667,7 +658,6 @@ define_machine(iseries) { .calibrate_decr = generic_calibrate_decr, .progress = iSeries_progress, .probe = iseries_probe, - .check_legacy_ioport = iseries_check_legacy_ioport, .ioremap = iseries_ioremap, .iounmap = iseries_iounmap, /* XXX Implement enable_pmcs for iSeries */ diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c index e2100ec..2ca2d8a 100644 --- a/arch/powerpc/platforms/iseries/viopath.c +++ b/arch/powerpc/platforms/iseries/viopath.c @@ -155,7 +155,7 @@ static int proc_viopath_show(struct seq_file *m, void *v) node = of_find_node_by_path("/"); sysid = NULL; if (node != NULL) - sysid = get_property(node, "system-id", NULL); + sysid = of_get_property(node, "system-id", NULL); if (sysid == NULL) seq_printf(m, "SRLNBR=<UNKNOWN>\n"); diff --git a/arch/powerpc/platforms/maple/Kconfig b/arch/powerpc/platforms/maple/Kconfig new file mode 100644 index 0000000..f7c95eb --- /dev/null +++ b/arch/powerpc/platforms/maple/Kconfig @@ -0,0 +1,17 @@ +config PPC_MAPLE + depends on PPC_MULTIPLATFORM && PPC64 + bool "Maple 970FX Evaluation Board" + select MPIC + select U3_DART + select MPIC_U3_HT_IRQS + 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> diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c index 73c5990..b1d3b99 100644 --- a/arch/powerpc/platforms/maple/pci.c +++ b/arch/powerpc/platforms/maple/pci.c @@ -44,11 +44,11 @@ static int __init fixup_one_level_bus_range(struct device_node *node, int higher int len; /* For PCI<->PCI bridges or CardBus bridges, we go down */ - class_code = get_property(node, "class-code", NULL); + class_code = of_get_property(node, "class-code", NULL); if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI && (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) continue; - 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[1] > higher) higher = bus_range[1]; @@ -77,7 +77,7 @@ static void __init fixup_bus_range(struct device_node *bridge) bridge->full_name); return; } - bus_range = (int *)prop->value; + bus_range = prop->value; bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]); } @@ -454,7 +454,7 @@ static int __init add_bridge(struct device_node *dev) DBG("Adding PCI host bridge %s\n", dev->full_name); - 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)) { printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n", dev->full_name); diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index 82d3f9e..2a30c5b 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c @@ -32,7 +32,6 @@ #include <linux/initrd.h> #include <linux/vt_kern.h> #include <linux/console.h> -#include <linux/ide.h> #include <linux/pci.h> #include <linux/adb.h> #include <linux/cuda.h> @@ -114,8 +113,8 @@ static void maple_restart(char *cmd) printk(KERN_EMERG "Maple: Unable to find Service Processor\n"); goto fail; } - maple_nvram_offset = get_property(sp, "restart-addr", NULL); - maple_nvram_command = get_property(sp, "restart-value", NULL); + maple_nvram_offset = of_get_property(sp, "restart-addr", NULL); + maple_nvram_command = of_get_property(sp, "restart-value", NULL); of_node_put(sp); /* send command */ @@ -141,8 +140,8 @@ static void maple_power_off(void) printk(KERN_EMERG "Maple: Unable to find Service Processor\n"); goto fail; } - maple_nvram_offset = get_property(sp, "power-off-addr", NULL); - maple_nvram_command = get_property(sp, "power-off-value", NULL); + maple_nvram_offset = of_get_property(sp, "power-off-addr", NULL); + maple_nvram_command = of_get_property(sp, "power-off-value", NULL); of_node_put(sp); /* send command */ @@ -249,8 +248,8 @@ static void __init maple_init_IRQ(void) /* Find address list in /platform-open-pic */ root = of_find_node_by_path("/"); - naddr = prom_n_addr_cells(root); - opprop = get_property(root, "platform-open-pic", &opplen); + naddr = of_n_addr_cells(root); + opprop = of_get_property(root, "platform-open-pic", &opplen); if (opprop != 0) { openpic_addr = of_read_number(opprop, naddr); has_isus = (opplen > naddr); @@ -261,11 +260,11 @@ static void __init maple_init_IRQ(void) BUG_ON(openpic_addr == 0); /* Check for a big endian MPIC */ - if (get_property(np, "big-endian", NULL) != NULL) + if (of_get_property(np, "big-endian", NULL) != NULL) flags |= MPIC_BIG_ENDIAN; /* XXX Maple specific bits */ - flags |= MPIC_BROKEN_U3 | MPIC_WANTS_RESET; + flags |= MPIC_U3_HT_IRQS | MPIC_WANTS_RESET; /* All U3/U4 are big-endian, older SLOF firmware doesn't encode this */ flags |= MPIC_BIG_ENDIAN; diff --git a/arch/powerpc/platforms/pasemi/Kconfig b/arch/powerpc/platforms/pasemi/Kconfig index 68dc529..eb4dbc7 100644 --- a/arch/powerpc/platforms/pasemi/Kconfig +++ b/arch/powerpc/platforms/pasemi/Kconfig @@ -1,3 +1,15 @@ +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 + menu "PA Semi PWRficient options" depends on PPC_PASEMI @@ -7,4 +19,11 @@ config PPC_PASEMI_IOMMU help IOMMU support for PA6T-1682M +config PPC_PASEMI_MDIO + depends on PHYLIB + tristate "MDIO support via GPIO" + default y + help + Driver for MDIO via GPIO on PWRficient platforms + endmenu diff --git a/arch/powerpc/platforms/pasemi/Makefile b/arch/powerpc/platforms/pasemi/Makefile index e657cca..2cd2a4f 100644 --- a/arch/powerpc/platforms/pasemi/Makefile +++ b/arch/powerpc/platforms/pasemi/Makefile @@ -1,2 +1,3 @@ obj-y += setup.o pci.o time.o idle.o powersave.o iommu.o - +obj-$(CONFIG_PPC_PASEMI_MDIO) += gpio_mdio.o +obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += cpufreq.o diff --git a/arch/powerpc/platforms/pasemi/cpufreq.c b/arch/powerpc/platforms/pasemi/cpufreq.c new file mode 100644 index 0000000..2a57d60 --- /dev/null +++ b/arch/powerpc/platforms/pasemi/cpufreq.c @@ -0,0 +1,308 @@ +/* + * Copyright (C) 2007 PA Semi, Inc + * + * Authors: Egor Martovetsky <egor@pasemi.com> + * Olof Johansson <olof@lixom.net> + * + * Maintained by: Olof Johansson <olof@lixom.net> + * + * Based on arch/powerpc/platforms/cell/cbe_cpufreq.c: + * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 + * + * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include <linux/cpufreq.h> +#include <linux/timer.h> + +#include <asm/hw_irq.h> +#include <asm/io.h> +#include <asm/prom.h> + +#define SDCASR_REG 0x0100 +#define SDCASR_REG_STRIDE 0x1000 +#define SDCPWR_CFGA0_REG 0x0100 +#define SDCPWR_PWST0_REG 0x0000 +#define SDCPWR_GIZTIME_REG 0x0440 + +/* SDCPWR_GIZTIME_REG fields */ +#define SDCPWR_GIZTIME_GR 0x80000000 +#define SDCPWR_GIZTIME_LONGLOCK 0x000000ff + +/* Offset of ASR registers from SDC base */ +#define SDCASR_OFFSET 0x120000 + +static void __iomem *sdcpwr_mapbase; +static void __iomem *sdcasr_mapbase; + +static DEFINE_MUTEX(pas_switch_mutex); + +/* Current astate, is used when waking up from power savings on + * one core, in case the other core has switched states during + * the idle time. + */ +static int current_astate; + +/* We support 5(A0-A4) power states excluding turbo(A5-A6) modes */ +static struct cpufreq_frequency_table pas_freqs[] = { + {0, 0}, + {1, 0}, + {2, 0}, + {3, 0}, + {4, 0}, + {0, CPUFREQ_TABLE_END}, +}; + +static struct freq_attr *pas_cpu_freqs_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + +/* + * hardware specific functions + */ + +static int get_astate_freq(int astate) +{ + u32 ret; + ret = in_le32(sdcpwr_mapbase + SDCPWR_CFGA0_REG + (astate * 0x10)); + + return ret & 0x3f; +} + +static int get_cur_astate(int cpu) +{ + u32 ret; + + ret = in_le32(sdcpwr_mapbase + SDCPWR_PWST0_REG); + ret = (ret >> (cpu * 4)) & 0x7; + + return ret; +} + +static int get_gizmo_latency(void) +{ + u32 giztime, ret; + + giztime = in_le32(sdcpwr_mapbase + SDCPWR_GIZTIME_REG); + + /* just provide the upper bound */ + if (giztime & SDCPWR_GIZTIME_GR) + ret = (giztime & SDCPWR_GIZTIME_LONGLOCK) * 128000; + else + ret = (giztime & SDCPWR_GIZTIME_LONGLOCK) * 1000; + + return ret; +} + +static void set_astate(int cpu, unsigned int astate) +{ + u64 flags; + + /* Return if called before init has run */ + if (unlikely(!sdcasr_mapbase)) + return; + + local_irq_save(flags); + + out_le32(sdcasr_mapbase + SDCASR_REG + SDCASR_REG_STRIDE*cpu, astate); + + local_irq_restore(flags); +} + +void restore_astate(int cpu) +{ + set_astate(cpu, current_astate); +} + +/* + * cpufreq functions + */ + +static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy) +{ + const u32 *max_freqp; + u32 max_freq; + int i, cur_astate; + struct resource res; + struct device_node *cpu, *dn; + int err = -ENODEV; + + cpu = of_get_cpu_node(policy->cpu, NULL); + + if (!cpu) + goto out; + + dn = of_find_compatible_node(NULL, "sdc", "1682m-sdc"); + if (!dn) + goto out; + err = of_address_to_resource(dn, 0, &res); + of_node_put(dn); + if (err) + goto out; + sdcasr_mapbase = ioremap(res.start + SDCASR_OFFSET, 0x2000); + if (!sdcasr_mapbase) { + err = -EINVAL; + goto out; + } + + dn = of_find_compatible_node(NULL, "gizmo", "1682m-gizmo"); + if (!dn) { + err = -ENODEV; + goto out_unmap_sdcasr; + } + err = of_address_to_resource(dn, 0, &res); + of_node_put(dn); + if (err) + goto out_unmap_sdcasr; + sdcpwr_mapbase = ioremap(res.start, 0x1000); + if (!sdcpwr_mapbase) { + err = -EINVAL; + goto out_unmap_sdcasr; + } + + pr_debug("init cpufreq on CPU %d\n", policy->cpu); + + max_freqp = of_get_property(cpu, "clock-frequency", NULL); + if (!max_freqp) { + err = -EINVAL; + goto out_unmap_sdcpwr; + } + + /* we need the freq in kHz */ + max_freq = *max_freqp / 1000; + + pr_debug("max clock-frequency is at %u kHz\n", max_freq); + pr_debug("initializing frequency table\n"); + + /* initialize frequency table */ + for (i=0; pas_freqs[i].frequency!=CPUFREQ_TABLE_END; i++) { + pas_freqs[i].frequency = get_astate_freq(pas_freqs[i].index) * 100000; + pr_debug("%d: %d\n", i, pas_freqs[i].frequency); + } + + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; + + policy->cpuinfo.transition_latency = get_gizmo_latency(); + + cur_astate = get_cur_astate(policy->cpu); + pr_debug("current astate is at %d\n",cur_astate); + + policy->cur = pas_freqs[cur_astate].frequency; + policy->cpus = cpu_online_map; + + cpufreq_frequency_table_get_attr(pas_freqs, policy->cpu); + + /* this ensures that policy->cpuinfo_min and policy->cpuinfo_max + * are set correctly + */ + return cpufreq_frequency_table_cpuinfo(policy, pas_freqs); + +out_unmap_sdcpwr: + iounmap(sdcpwr_mapbase); + +out_unmap_sdcasr: + iounmap(sdcasr_mapbase); +out: + return err; +} + +static int pas_cpufreq_cpu_exit(struct cpufreq_policy *policy) +{ + if (sdcasr_mapbase) + iounmap(sdcasr_mapbase); + if (sdcpwr_mapbase) + iounmap(sdcpwr_mapbase); + + cpufreq_frequency_table_put_attr(policy->cpu); + return 0; +} + +static int pas_cpufreq_verify(struct cpufreq_policy *policy) +{ + return cpufreq_frequency_table_verify(policy, pas_freqs); +} + +static int pas_cpufreq_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + struct cpufreq_freqs freqs; + int pas_astate_new; + int i; + + cpufreq_frequency_table_target(policy, + pas_freqs, + target_freq, + relation, + &pas_astate_new); + + freqs.old = policy->cur; + freqs.new = pas_freqs[pas_astate_new].frequency; + freqs.cpu = policy->cpu; + + mutex_lock(&pas_switch_mutex); + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + + pr_debug("setting frequency for cpu %d to %d kHz, 1/%d of max frequency\n", + policy->cpu, + pas_freqs[pas_astate_new].frequency, + pas_freqs[pas_astate_new].index); + + current_astate = pas_astate_new; + + for_each_online_cpu(i) + set_astate(i, pas_astate_new); + + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + mutex_unlock(&pas_switch_mutex); + + return 0; +} + +static struct cpufreq_driver pas_cpufreq_driver = { + .name = "pas-cpufreq", + .owner = THIS_MODULE, + .flags = CPUFREQ_CONST_LOOPS, + .init = pas_cpufreq_cpu_init, + .exit = pas_cpufreq_cpu_exit, + .verify = pas_cpufreq_verify, + .target = pas_cpufreq_target, + .attr = pas_cpu_freqs_attr, +}; + +/* + * module init and destoy + */ + +static int __init pas_cpufreq_init(void) +{ + if (!machine_is_compatible("PA6T-1682M")) + return -ENODEV; + + return cpufreq_register_driver(&pas_cpufreq_driver); +} + +static void __exit pas_cpufreq_exit(void) +{ + cpufreq_unregister_driver(&pas_cpufreq_driver); +} + +module_init(pas_cpufreq_init); +module_exit(pas_cpufreq_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Egor Martovetsky <egor@pasemi.com>, Olof Johansson <olof@lixom.net>"); diff --git a/arch/powerpc/platforms/pasemi/gpio_mdio.c b/arch/powerpc/platforms/pasemi/gpio_mdio.c new file mode 100644 index 0000000..c91a335 --- /dev/null +++ b/arch/powerpc/platforms/pasemi/gpio_mdio.c @@ -0,0 +1,339 @@ +/* + * Copyright (C) 2006-2007 PA Semi, Inc + * + * Author: Olof Johansson, PA Semi + * + * Maintained by: Olof Johansson <olof@lixom.net> + * + * Based on drivers/net/fs_enet/mii-bitbang.c. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/io.h> +#include <linux/module.h> +#include <linux/types.h> +#include <linux/sched.h> +#include <linux/errno.h> +#include <linux/ioport.h> +#include <linux/interrupt.h> +#include <linux/phy.h> +#include <linux/platform_device.h> +#include <asm/of_platform.h> + +#define DELAY 1 + +static void __iomem *gpio_regs; + +struct gpio_priv { + int mdc_pin; + int mdio_pin; +}; + +#define MDC_PIN(bus) (((struct gpio_priv *)bus->priv)->mdc_pin) +#define MDIO_PIN(bus) (((struct gpio_priv *)bus->priv)->mdio_pin) + +static inline void mdio_lo(struct mii_bus *bus) +{ + out_le32(gpio_regs+0x10, 1 << MDIO_PIN(bus)); +} + +static inline void mdio_hi(struct mii_bus *bus) +{ + out_le32(gpio_regs, 1 << MDIO_PIN(bus)); +} + +static inline void mdc_lo(struct mii_bus *bus) +{ + out_le32(gpio_regs+0x10, 1 << MDC_PIN(bus)); +} + +static inline void mdc_hi(struct mii_bus *bus) +{ + out_le32(gpio_regs, 1 << MDC_PIN(bus)); +} + +static inline void mdio_active(struct mii_bus *bus) +{ + out_le32(gpio_regs+0x20, (1 << MDC_PIN(bus)) | (1 << MDIO_PIN(bus))); +} + +static inline void mdio_tristate(struct mii_bus *bus) +{ + out_le32(gpio_regs+0x30, (1 << MDIO_PIN(bus))); +} + +static inline int mdio_read(struct mii_bus *bus) +{ + return !!(in_le32(gpio_regs+0x40) & (1 << MDIO_PIN(bus))); +} + +static void clock_out(struct mii_bus *bus, int bit) +{ + if (bit) + mdio_hi(bus); + else + mdio_lo(bus); + udelay(DELAY); + mdc_hi(bus); + udelay(DELAY); + mdc_lo(bus); +} + +/* Utility to send the preamble, address, and register (common to read and write). */ +static void bitbang_pre(struct mii_bus *bus, int read, u8 addr, u8 reg) +{ + int i; + + /* CFE uses a really long preamble (40 bits). We'll do the same. */ + mdio_active(bus); + for (i = 0; i < 40; i++) { + clock_out(bus, 1); + } + + /* send the start bit (01) and the read opcode (10) or write (10) */ + clock_out(bus, 0); + clock_out(bus, 1); + + clock_out(bus, read); + clock_out(bus, !read); + + /* send the PHY address */ + for (i = 0; i < 5; i++) { + clock_out(bus, (addr & 0x10) != 0); + addr <<= 1; + } + + /* send the register address */ + for (i = 0; i < 5; i++) { + clock_out(bus, (reg & 0x10) != 0); + reg <<= 1; + } +} + +static int gpio_mdio_read(struct mii_bus *bus, int phy_id, int location) +{ + u16 rdreg; + int ret, i; + u8 addr = phy_id & 0xff; + u8 reg = location & 0xff; + + bitbang_pre(bus, 1, addr, reg); + + /* tri-state our MDIO I/O pin so we can read */ + mdio_tristate(bus); + udelay(DELAY); + mdc_hi(bus); + udelay(DELAY); + mdc_lo(bus); + + /* read 16 bits of register data, MSB first */ + rdreg = 0; + for (i = 0; i < 16; i++) { + mdc_lo(bus); + udelay(DELAY); + mdc_hi(bus); + udelay(DELAY); + mdc_lo(bus); + udelay(DELAY); + rdreg <<= 1; + rdreg |= mdio_read(bus); + } + + mdc_hi(bus); + udelay(DELAY); + mdc_lo(bus); + udelay(DELAY); + + ret = rdreg; + + return ret; +} + +static int gpio_mdio_write(struct mii_bus *bus, int phy_id, int location, u16 val) +{ + int i; + + u8 addr = phy_id & 0xff; + u8 reg = location & 0xff; + u16 value = val & 0xffff; + + bitbang_pre(bus, 0, addr, reg); + + /* send the turnaround (10) */ + mdc_lo(bus); + mdio_hi(bus); + udelay(DELAY); + mdc_hi(bus); + udelay(DELAY); + mdc_lo(bus); + mdio_lo(bus); + udelay(DELAY); + mdc_hi(bus); + udelay(DELAY); + + /* write 16 bits of register data, MSB first */ + for (i = 0; i < 16; i++) { + mdc_lo(bus); + if (value & 0x8000) + mdio_hi(bus); + else + mdio_lo(bus); + udelay(DELAY); + mdc_hi(bus); + udelay(DELAY); + value <<= 1; + } + + /* + * Tri-state the MDIO line. + */ + mdio_tristate(bus); + mdc_lo(bus); + udelay(DELAY); + mdc_hi(bus); + udelay(DELAY); + return 0; +} + +static int gpio_mdio_reset(struct mii_bus *bus) +{ + /*nothing here - dunno how to reset it*/ + return 0; +} + + +static int __devinit gpio_mdio_probe(struct of_device *ofdev, + const struct of_device_id *match) +{ + struct device *dev = &ofdev->dev; + struct device_node *np = ofdev->node; + struct device_node *gpio_np; + struct mii_bus *new_bus; + struct resource res; + struct gpio_priv *priv; + const unsigned int *prop; + int err = 0; + int i; + + gpio_np = of_find_compatible_node(NULL, "gpio", "1682m-gpio"); + + if (!gpio_np) + return -ENODEV; + + err = of_address_to_resource(gpio_np, 0, &res); + of_node_put(gpio_np); + + if (err) + return -EINVAL; + + if (!gpio_regs) + gpio_regs = ioremap(res.start, 0x100); + + if (!gpio_regs) + return -EPERM; + + priv = kzalloc(sizeof(struct gpio_priv), GFP_KERNEL); + if (priv == NULL) + return -ENOMEM; + + new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL); + + if (new_bus == NULL) + return -ENOMEM; + + new_bus->name = "pasemi gpio mdio bus", + new_bus->read = &gpio_mdio_read, + new_bus->write = &gpio_mdio_write, + new_bus->reset = &gpio_mdio_reset, + + prop = of_get_property(np, "reg", NULL); + new_bus->id = *prop; + new_bus->priv = priv; + + new_bus->phy_mask = 0; + + new_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL); + for(i = 0; i < PHY_MAX_ADDR; ++i) + new_bus->irq[i] = irq_create_mapping(NULL, 10); + + + prop = of_get_property(np, "mdc-pin", NULL); + priv->mdc_pin = *prop; + + prop = of_get_property(np, "mdio-pin", NULL); + priv->mdio_pin = *prop; + + new_bus->dev = dev; + dev_set_drvdata(dev, new_bus); + + err = mdiobus_register(new_bus); + + if (0 != err) { + printk(KERN_ERR "%s: Cannot register as MDIO bus, err %d\n", + new_bus->name, err); + goto bus_register_fail; + } + + return 0; + +bus_register_fail: + kfree(new_bus); + + return err; +} + + +static int gpio_mdio_remove(struct of_device *dev) +{ + struct mii_bus *bus = dev_get_drvdata(&dev->dev); + + mdiobus_unregister(bus); + + dev_set_drvdata(&dev->dev, NULL); + + kfree(bus->priv); + bus->priv = NULL; + kfree(bus); + + return 0; +} + +static struct of_device_id gpio_mdio_match[] = +{ + { + .compatible = "gpio-mdio", + }, + {}, +}; + +static struct of_platform_driver gpio_mdio_driver = +{ + .name = "gpio-mdio-bitbang", + .match_table = gpio_mdio_match, + .probe = gpio_mdio_probe, + .remove = gpio_mdio_remove, +}; + +int gpio_mdio_init(void) +{ + return of_register_platform_driver(&gpio_mdio_driver); +} + +void gpio_mdio_exit(void) +{ + of_unregister_platform_driver(&gpio_mdio_driver); +} +device_initcall(gpio_mdio_init); + diff --git a/arch/powerpc/platforms/pasemi/idle.c b/arch/powerpc/platforms/pasemi/idle.c index 1ca3ff3..5985ce0 100644 --- a/arch/powerpc/platforms/pasemi/idle.c +++ b/arch/powerpc/platforms/pasemi/idle.c @@ -61,6 +61,10 @@ static int pasemi_system_reset_exception(struct pt_regs *regs) /* do system reset */ return 0; } + + /* Set higher astate since we come out of power savings at 0 */ + restore_astate(hard_smp_processor_id()); + /* everything handled */ regs->msr |= MSR_RI; return 1; @@ -68,6 +72,11 @@ static int pasemi_system_reset_exception(struct pt_regs *regs) void __init pasemi_idle_init(void) { +#ifndef CONFIG_PPC_PASEMI_CPUFREQ + printk(KERN_WARNING "No cpufreq driver, powersavings modes disabled\n"); + current_mode = 0; +#endif + ppc_md.system_reset_exception = pasemi_system_reset_exception; ppc_md.power_save = modes[current_mode].entry; printk(KERN_INFO "Using PA6T idle loop (%s)\n", modes[current_mode].name); diff --git a/arch/powerpc/platforms/pasemi/iommu.c b/arch/powerpc/platforms/pasemi/iommu.c index 71dbf1a..95fa6a7 100644 --- a/arch/powerpc/platforms/pasemi/iommu.c +++ b/arch/powerpc/platforms/pasemi/iommu.c @@ -249,13 +249,13 @@ void iommu_init_early_pasemi(void) iommu_off = 1; #else iommu_off = of_chosen && - get_property(of_chosen, "linux,iommu-off", NULL); + of_get_property(of_chosen, "linux,iommu-off", NULL); #endif if (iommu_off) { /* Direct I/O, IOMMU off */ ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_null; ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_null; - pci_dma_ops = &dma_direct_ops; + set_pci_dma_ops(&dma_direct_ops); return; } @@ -266,7 +266,7 @@ void iommu_init_early_pasemi(void) ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pasemi; ppc_md.tce_build = iobmap_build; ppc_md.tce_free = iobmap_free; - pci_dma_ops = &dma_iommu_ops; + set_pci_dma_ops(&dma_iommu_ops); } void __init alloc_iobmap_l2(void) diff --git a/arch/powerpc/platforms/pasemi/pasemi.h b/arch/powerpc/platforms/pasemi/pasemi.h index 2d3927e..be84954 100644 --- a/arch/powerpc/platforms/pasemi/pasemi.h +++ b/arch/powerpc/platforms/pasemi/pasemi.h @@ -14,6 +14,14 @@ extern void __init pasemi_idle_init(void); extern void idle_spin(void); extern void idle_doze(void); +/* Restore astate to last set */ +#ifdef CONFIG_PPC_PASEMI_CPUFREQ +extern void restore_astate(int cpu); +#else +static inline void restore_astate(int cpu) +{ +} +#endif #endif /* _PASEMI_PASEMI_H */ diff --git a/arch/powerpc/platforms/pasemi/pci.c b/arch/powerpc/platforms/pasemi/pci.c index 7ecb2ba..056243d 100644 --- a/arch/powerpc/platforms/pasemi/pci.c +++ b/arch/powerpc/platforms/pasemi/pci.c @@ -33,7 +33,17 @@ #define PA_PXP_CFA(bus, devfn, off) (((bus) << 20) | ((devfn) << 12) | (off)) -#define CONFIG_OFFSET_VALID(off) ((off) < 4096) +static inline int pa_pxp_offset_valid(u8 bus, u8 devfn, int offset) +{ + /* Device 0 Function 0 is special: It's config space spans function 1 as + * well, so allow larger offset. It's really a two-function device but the + * second function does not probe. + */ + if (bus == 0 && devfn == 0) + return offset < 8192; + else + return offset < 4096; +} static void volatile __iomem *pa_pxp_cfg_addr(struct pci_controller *hose, u8 bus, u8 devfn, int offset) @@ -51,7 +61,7 @@ static int pa_pxp_read_config(struct pci_bus *bus, unsigned int devfn, if (!hose) return PCIBIOS_DEVICE_NOT_FOUND; - if (!CONFIG_OFFSET_VALID(offset)) + if (!pa_pxp_offset_valid(bus->number, devfn, offset)) return PCIBIOS_BAD_REGISTER_NUMBER; addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset); @@ -85,7 +95,7 @@ static int pa_pxp_write_config(struct pci_bus *bus, unsigned int devfn, if (!hose) return PCIBIOS_DEVICE_NOT_FOUND; - if (!CONFIG_OFFSET_VALID(offset)) + if (!pa_pxp_offset_valid(bus->number, devfn, offset)) return PCIBIOS_BAD_REGISTER_NUMBER; addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset); diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c index 449cf1a..f88f0ec 100644 --- a/arch/powerpc/platforms/pasemi/setup.c +++ b/arch/powerpc/platforms/pasemi/setup.c @@ -35,6 +35,7 @@ #include <asm/mpic.h> #include <asm/smp.h> #include <asm/time.h> +#include <asm/of_platform.h> #include "pasemi.h" @@ -101,12 +102,6 @@ void __init pas_setup_arch(void) pasemi_idle_init(); } -/* No legacy IO on our parts */ -static int pas_check_legacy_ioport(unsigned int baseport) -{ - return -ENODEV; -} - static __init void pas_init_IRQ(void) { struct device_node *np; @@ -136,8 +131,8 @@ static __init void pas_init_IRQ(void) /* Find address list in /platform-open-pic */ root = of_find_node_by_path("/"); - naddr = prom_n_addr_cells(root); - opprop = get_property(root, "platform-open-pic", &opplen); + naddr = of_n_addr_cells(root); + opprop = of_get_property(root, "platform-open-pic", &opplen); if (!opprop) { printk(KERN_ERR "No platform-open-pic property.\n"); of_node_put(root); @@ -147,7 +142,7 @@ static __init void pas_init_IRQ(void) printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr); mpic = mpic_alloc(mpic_node, openpic_addr, - MPIC_PRIMARY|MPIC_LARGE_VECTORS, + MPIC_PRIMARY|MPIC_LARGE_VECTORS|MPIC_WANTS_RESET, 0, 0, " PAS-OPIC "); BUG_ON(!mpic); @@ -209,6 +204,20 @@ static void __init pas_init_early(void) iommu_init_early_pasemi(); } +static struct of_device_id pasemi_bus_ids[] = { + { .type = "sdc", }, + {}, +}; + +static int __init pasemi_publish_devices(void) +{ + /* Publish OF platform devices for southbridge IOs */ + of_platform_bus_probe(NULL, pasemi_bus_ids, NULL); + + return 0; +} +device_initcall(pasemi_publish_devices); + /* * Called very early, MMU is off, device-tree isn't unflattened @@ -237,7 +246,6 @@ define_machine(pas) { .restart = pas_restart, .get_boot_time = pas_get_boot_time, .calibrate_decr = generic_calibrate_decr, - .check_legacy_ioport = pas_check_legacy_ioport, .progress = pas_progress, .machine_check_exception = pas_machine_check_handler, .pci_irq_fixup = pas_pci_irq_fixup, diff --git a/arch/powerpc/platforms/powermac/Kconfig b/arch/powerpc/platforms/powermac/Kconfig new file mode 100644 index 0000000..5b7afe5 --- /dev/null +++ b/arch/powerpc/platforms/powermac/Kconfig @@ -0,0 +1,20 @@ +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_U3_HT_IRQS + select GENERIC_TBSYNC + select PPC_970_NAP + default y + + diff --git a/arch/powerpc/platforms/powermac/backlight.c b/arch/powerpc/platforms/powermac/backlight.c index de7440e..d679964 100644 --- a/arch/powerpc/platforms/powermac/backlight.c +++ b/arch/powerpc/platforms/powermac/backlight.c @@ -56,13 +56,16 @@ struct backlight_device *pmac_backlight; int pmac_has_backlight_type(const char *type) { - struct device_node* bk_node = find_devices("backlight"); + struct device_node* bk_node = of_find_node_by_name(NULL, "backlight"); if (bk_node) { - const char *prop = get_property(bk_node, + const char *prop = of_get_property(bk_node, "backlight-control", NULL); - if (prop && strncmp(prop, type, strlen(type)) == 0) + if (prop && strncmp(prop, type, strlen(type)) == 0) { + of_node_put(bk_node); return 1; + } + of_node_put(bk_node); } return 0; diff --git a/arch/powerpc/platforms/powermac/cpufreq_32.c b/arch/powerpc/platforms/powermac/cpufreq_32.c index c2b6b413..8943a94 100644 --- a/arch/powerpc/platforms/powermac/cpufreq_32.c +++ b/arch/powerpc/platforms/powermac/cpufreq_32.c @@ -421,7 +421,7 @@ static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy) static u32 read_gpio(struct device_node *np) { - const u32 *reg = get_property(np, "reg", NULL); + const u32 *reg = of_get_property(np, "reg", NULL); u32 offset; if (reg == NULL) @@ -521,13 +521,14 @@ static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode) int lenp, rc; const u32 *freqs, *ratio; - freqs = get_property(cpunode, "bus-frequencies", &lenp); + freqs = of_get_property(cpunode, "bus-frequencies", &lenp); lenp /= sizeof(u32); if (freqs == NULL || lenp != 2) { printk(KERN_ERR "cpufreq: bus-frequencies incorrect or missing\n"); return 1; } - ratio = get_property(cpunode, "processor-to-bus-ratio*2", NULL); + ratio = of_get_property(cpunode, "processor-to-bus-ratio*2", + NULL); if (ratio == NULL) { printk(KERN_ERR "cpufreq: processor-to-bus-ratio*2 missing\n"); return 1; @@ -562,7 +563,7 @@ static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode) /* If we use the PMU, look for the min & max frequencies in the * device-tree */ - value = get_property(cpunode, "min-clock-frequency", NULL); + value = of_get_property(cpunode, "min-clock-frequency", NULL); if (!value) return 1; low_freq = (*value) / 1000; @@ -571,7 +572,7 @@ static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode) if (low_freq < 100000) low_freq *= 10; - value = get_property(cpunode, "max-clock-frequency", NULL); + value = of_get_property(cpunode, "max-clock-frequency", NULL); if (!value) return 1; hi_freq = (*value) / 1000; @@ -585,7 +586,7 @@ static int pmac_cpufreq_init_7447A(struct device_node *cpunode) { struct device_node *volt_gpio_np; - if (get_property(cpunode, "dynamic-power-step", NULL) == NULL) + if (of_get_property(cpunode, "dynamic-power-step", NULL) == NULL) return 1; volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select"); @@ -614,11 +615,11 @@ static int pmac_cpufreq_init_750FX(struct device_node *cpunode) u32 pvr; const u32 *value; - if (get_property(cpunode, "dynamic-power-step", NULL) == NULL) + if (of_get_property(cpunode, "dynamic-power-step", NULL) == NULL) return 1; hi_freq = cur_freq; - value = get_property(cpunode, "reduced-clock-frequency", NULL); + value = of_get_property(cpunode, "reduced-clock-frequency", NULL); if (!value) return 1; low_freq = (*value) / 1000; @@ -657,19 +658,19 @@ static int __init pmac_cpufreq_setup(void) return 0; /* Assume only one CPU */ - cpunode = find_type_devices("cpu"); + cpunode = of_find_node_by_type(NULL, "cpu"); if (!cpunode) goto out; /* Get current cpu clock freq */ - value = get_property(cpunode, "clock-frequency", NULL); + value = of_get_property(cpunode, "clock-frequency", NULL); if (!value) goto out; cur_freq = (*value) / 1000; /* Check for 7447A based MacRISC3 */ if (machine_is_compatible("MacRISC3") && - get_property(cpunode, "dynamic-power-step", NULL) && + of_get_property(cpunode, "dynamic-power-step", NULL) && PVR_VER(mfspr(SPRN_PVR)) == 0x8003) { pmac_cpufreq_init_7447A(cpunode); /* Check for other MacRISC3 machines */ @@ -707,6 +708,7 @@ static int __init pmac_cpufreq_setup(void) else if (PVR_VER(mfspr(SPRN_PVR)) == 0x7000) pmac_cpufreq_init_750FX(cpunode); out: + of_node_put(cpunode); if (set_speed_proc == NULL) return -ENODEV; diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c index 9d22361..567d552 100644 --- a/arch/powerpc/platforms/powermac/cpufreq_64.c +++ b/arch/powerpc/platforms/powermac/cpufreq_64.c @@ -410,7 +410,7 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpus) /* Get first CPU node */ for (cpunode = NULL; (cpunode = of_get_next_child(cpus, cpunode)) != NULL;) { - const u32 *reg = get_property(cpunode, "reg", NULL); + const u32 *reg = of_get_property(cpunode, "reg", NULL); if (reg == NULL || (*reg) != 0) continue; if (!strcmp(cpunode->type, "cpu")) @@ -422,7 +422,7 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpus) } /* Check 970FX for now */ - valp = get_property(cpunode, "cpu-version", NULL); + valp = of_get_property(cpunode, "cpu-version", NULL); if (!valp) { DBG("No cpu-version property !\n"); goto bail_noprops; @@ -434,7 +434,7 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpus) } /* Look for the powertune data in the device-tree */ - g5_pmode_data = get_property(cpunode, "power-mode-data",&psize); + g5_pmode_data = of_get_property(cpunode, "power-mode-data",&psize); if (!g5_pmode_data) { DBG("No power-mode-data !\n"); goto bail_noprops; @@ -493,7 +493,7 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpus) * half freq in this version. So far, I haven't yet seen a machine * supporting anything else. */ - valp = get_property(cpunode, "clock-frequency", NULL); + valp = of_get_property(cpunode, "clock-frequency", NULL); if (!valp) return -ENODEV; max_freq = (*valp)/1000; @@ -563,7 +563,7 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus) /* Lookup the cpuid eeprom node */ cpuid = of_find_node_by_path("/u3@0,f8000000/i2c@f8001000/cpuid@a0"); if (cpuid != NULL) - eeprom = get_property(cpuid, "cpuid", NULL); + eeprom = of_get_property(cpuid, "cpuid", NULL); if (eeprom == NULL) { printk(KERN_ERR "cpufreq: Can't find cpuid EEPROM !\n"); rc = -ENODEV; @@ -573,13 +573,13 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus) /* Lookup the i2c hwclock */ for (hwclock = NULL; (hwclock = of_find_node_by_name(hwclock, "i2c-hwclock")) != NULL;){ - const char *loc = get_property(hwclock, + const char *loc = of_get_property(hwclock, "hwctrl-location", NULL); if (loc == NULL) continue; if (strcmp(loc, "CPU CLOCK")) continue; - if (!get_property(hwclock, "platform-get-frequency", NULL)) + if (!of_get_property(hwclock, "platform-get-frequency", NULL)) continue; break; } @@ -638,7 +638,7 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus) */ /* Get max frequency from device-tree */ - valp = get_property(cpunode, "clock-frequency", NULL); + valp = of_get_property(cpunode, "clock-frequency", NULL); if (!valp) { printk(KERN_ERR "cpufreq: Can't find CPU frequency !\n"); rc = -ENODEV; diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index 24cc50c..52cfdd8 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c @@ -1044,6 +1044,7 @@ core99_reset_cpu(struct device_node *node, long param, long value) unsigned long flags; struct macio_chip *macio; struct device_node *np; + struct device_node *cpus; const int dflt_reset_lines[] = { KL_GPIO_RESET_CPU0, KL_GPIO_RESET_CPU1, KL_GPIO_RESET_CPU2, @@ -1053,12 +1054,12 @@ core99_reset_cpu(struct device_node *node, long param, long value) if (macio->type != macio_keylargo) return -ENODEV; - np = find_path_device("/cpus"); - if (np == NULL) + cpus = of_find_node_by_path("/cpus"); + if (cpus == NULL) return -ENODEV; - for (np = np->child; np != NULL; np = np->sibling) { - const u32 *num = get_property(np, "reg", NULL); - const u32 *rst = get_property(np, "soft-reset", NULL); + for (np = cpus->child; np != NULL; np = np->sibling) { + const u32 *num = of_get_property(np, "reg", NULL); + const u32 *rst = of_get_property(np, "soft-reset", NULL); if (num == NULL || rst == NULL) continue; if (param == *num) { @@ -1066,6 +1067,7 @@ core99_reset_cpu(struct device_node *node, long param, long value) break; } } + of_node_put(cpus); if (np == NULL || reset_io == 0) reset_io = dflt_reset_lines[param]; @@ -1095,7 +1097,7 @@ core99_usb_enable(struct device_node *node, long param, long value) macio->type != macio_intrepid) return -ENODEV; - prop = get_property(node, "AAPL,clock-id", NULL); + prop = of_get_property(node, "AAPL,clock-id", NULL); if (!prop) return -ENODEV; if (strncmp(prop, "usb0u048", 8) == 0) @@ -1497,17 +1499,18 @@ static long g5_reset_cpu(struct device_node *node, long param, long value) unsigned long flags; struct macio_chip *macio; struct device_node *np; + struct device_node *cpus; macio = &macio_chips[0]; if (macio->type != macio_keylargo2 && macio->type != macio_shasta) return -ENODEV; - np = find_path_device("/cpus"); - if (np == NULL) + cpus = of_find_node_by_path("/cpus"); + if (cpus == NULL) return -ENODEV; - for (np = np->child; np != NULL; np = np->sibling) { - const u32 *num = get_property(np, "reg", NULL); - const u32 *rst = get_property(np, "soft-reset", NULL); + for (np = cpus->child; np != NULL; np = np->sibling) { + const u32 *num = of_get_property(np, "reg", NULL); + const u32 *rst = of_get_property(np, "soft-reset", NULL); if (num == NULL || rst == NULL) continue; if (param == *num) { @@ -1515,6 +1518,7 @@ static long g5_reset_cpu(struct device_node *node, long param, long value) break; } } + of_node_put(cpus); if (np == NULL || reset_io == 0) return -ENODEV; @@ -2404,14 +2408,15 @@ static int __init probe_motherboard(void) struct macio_chip *macio = &macio_chips[0]; const char *model = NULL; struct device_node *dt; + int ret = 0; /* Lookup known motherboard type in device-tree. First try an * exact match on the "model" property, then try a "compatible" * match is none is found. */ - dt = find_devices("device-tree"); + dt = of_find_node_by_name(NULL, "device-tree"); if (dt != NULL) - model = get_property(dt, "model", NULL); + model = of_get_property(dt, "model", NULL); for(i=0; model && i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) { if (strcmp(model, pmac_mb_defs[i].model_string) == 0) { pmac_mb = pmac_mb_defs[i]; @@ -2474,15 +2479,18 @@ static int __init probe_motherboard(void) break; #endif /* CONFIG_POWER4 */ default: - return -ENODEV; + ret = -ENODEV; + goto done; } found: #ifndef CONFIG_POWER4 /* Fixup Hooper vs. Comet */ if (pmac_mb.model_id == PMAC_TYPE_HOOPER) { u32 __iomem * mach_id_ptr = ioremap(0xf3000034, 4); - if (!mach_id_ptr) - return -ENODEV; + if (!mach_id_ptr) { + ret = -ENODEV; + goto done; + } /* Here, I used to disable the media-bay on comet. It * appears this is wrong, the floppy connector is actually * a kind of media-bay and works with the current driver. @@ -2499,18 +2507,26 @@ found: * that all Apple OF revs did it properly, I do it the paranoid way. */ while (uninorth_base && uninorth_rev > 3) { - struct device_node *np = find_path_device("/cpus"); - if (!np || !np->child) { + struct device_node *cpus = of_find_node_by_path("/cpus"); + struct device_node *np; + + if (!cpus || !cpus->child) { printk(KERN_WARNING "Can't find CPU(s) in device tree !\n"); + of_node_put(cpus); break; } - np = np->child; + np = cpus->child; /* Nap mode not supported on SMP */ - if (np->sibling) + if (np->sibling) { + of_node_put(cpus); break; + } /* Nap mode not supported if flush-on-lock property is present */ - if (get_property(np, "flush-on-lock", NULL)) + if (of_get_property(np, "flush-on-lock", NULL)) { + of_node_put(cpus); break; + } + of_node_put(cpus); powersave_nap = 1; printk(KERN_DEBUG "Processor NAP mode on idle enabled.\n"); break; @@ -2532,7 +2548,9 @@ found: printk(KERN_INFO "PowerMac motherboard: %s\n", pmac_mb.model_name); - return 0; +done: + of_node_put(dt); + return ret; } /* Initialize the Core99 UniNorth host bridge and memory controller @@ -2558,7 +2576,7 @@ static void __init probe_uninorth(void) if (uninorth_node == NULL) return; - addrp = get_property(uninorth_node, "reg", NULL); + addrp = of_get_property(uninorth_node, "reg", NULL); if (addrp == NULL) return; address = of_translate_address(uninorth_node, addrp); @@ -2642,7 +2660,7 @@ static void __init probe_one_macio(const char *name, const char *compat, int typ return; } if (type == macio_keylargo || type == macio_keylargo2) { - const u32 *did = get_property(node, "device-id", NULL); + const u32 *did = of_get_property(node, "device-id", NULL); if (*did == 0x00000025) type = macio_pangea; if (*did == 0x0000003e) @@ -2655,7 +2673,7 @@ static void __init probe_one_macio(const char *name, const char *compat, int typ macio_chips[i].base = base; macio_chips[i].flags = MACIO_FLAG_SCCB_ON | MACIO_FLAG_SCCB_ON; macio_chips[i].name = macio_names[type]; - revp = get_property(node, "revision-id", NULL); + revp = of_get_property(node, "revision-id", NULL); if (revp) macio_chips[i].rev = *revp; printk(KERN_INFO "Found a %s mac-io controller, rev: %d, mapped at 0x%p\n", @@ -2706,8 +2724,8 @@ initial_serial_shutdown(struct device_node *np) int port_type = PMAC_SCC_ASYNC; int modem = 0; - slots = get_property(np, "slot-names", &len); - conn = get_property(np, "AAPL,connector", &len); + slots = of_get_property(np, "slot-names", &len); + conn = of_get_property(np, "AAPL,connector", &len); if (conn && (strcmp(conn, "infrared") == 0)) port_type = PMAC_SCC_IRDA; else if (device_is_compatible(np, "cobalt")) @@ -2735,12 +2753,14 @@ set_initial_features(void) * differenciate them all and since that hack was there for a long * time, I'll keep it around */ - if (macio_chips[0].type == macio_ohare && !find_devices("via-pmu")) { + if (macio_chips[0].type == macio_ohare) { struct macio_chip *macio = &macio_chips[0]; - MACIO_OUT32(OHARE_FCR, STARMAX_FEATURES); - } else if (macio_chips[0].type == macio_ohare) { - struct macio_chip *macio = &macio_chips[0]; - MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); + np = of_find_node_by_name(NULL, "via-pmu"); + if (np) + MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); + else + MACIO_OUT32(OHARE_FCR, STARMAX_FEATURES); + of_node_put(np); } else if (macio_chips[1].type == macio_ohare) { struct macio_chip *macio = &macio_chips[1]; MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); @@ -2833,14 +2853,13 @@ set_initial_features(void) } /* Switch airport off */ - np = find_devices("radio"); - while(np) { + for_each_node_by_name(np, "radio") { if (np && np->parent == macio_chips[0].of_node) { macio_chips[0].flags |= MACIO_FLAG_AIRPORT_ON; core99_airport_enable(np, 0, 0); } - np = np->next; } + of_node_put(np); } /* On all machines that support sound PM, switch sound off */ @@ -2860,16 +2879,12 @@ set_initial_features(void) #endif /* CONFIG_POWER4 */ /* On all machines, switch modem & serial ports off */ - np = find_devices("ch-a"); - while(np) { + for_each_node_by_name(np, "ch-a") initial_serial_shutdown(np); - np = np->next; - } - np = find_devices("ch-b"); - while(np) { + of_node_put(np); + for_each_node_by_name(np, "ch-b") initial_serial_shutdown(np); - np = np->next; - } + of_node_put(np); } void __init diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c index bfc4829..5430e14 100644 --- a/arch/powerpc/platforms/powermac/low_i2c.c +++ b/arch/powerpc/platforms/powermac/low_i2c.c @@ -491,7 +491,7 @@ static struct pmac_i2c_host_kw *__init kw_i2c_host_init(struct device_node *np) * on all i2c keywest nodes so far ... we would have to fallback * to macio parsing if that wasn't the case */ - addrp = get_property(np, "AAPL,address", NULL); + addrp = of_get_property(np, "AAPL,address", NULL); if (addrp == NULL) { printk(KERN_ERR "low_i2c: Can't find address for %s\n", np->full_name); @@ -505,13 +505,13 @@ static struct pmac_i2c_host_kw *__init kw_i2c_host_init(struct device_node *np) host->timeout_timer.function = kw_i2c_timeout; host->timeout_timer.data = (unsigned long)host; - psteps = get_property(np, "AAPL,address-step", NULL); + psteps = of_get_property(np, "AAPL,address-step", NULL); steps = psteps ? (*psteps) : 0x10; for (host->bsteps = 0; (steps & 0x01) == 0; host->bsteps++) steps >>= 1; /* Select interface rate */ host->speed = KW_I2C_MODE_25KHZ; - prate = get_property(np, "AAPL,i2c-rate", NULL); + prate = of_get_property(np, "AAPL,i2c-rate", NULL); if (prate) switch(*prate) { case 100: host->speed = KW_I2C_MODE_100KHZ; @@ -619,7 +619,7 @@ static void __init kw_i2c_probe(void) } else { for (child = NULL; (child = of_get_next_child(np, child)) != NULL;) { - const u32 *reg = get_property(child, + const u32 *reg = of_get_property(child, "reg", NULL); if (reg == NULL) continue; @@ -905,7 +905,7 @@ static void __init smu_i2c_probe(void) if (strcmp(busnode->type, "i2c") && strcmp(busnode->type, "i2c-bus")) continue; - reg = get_property(busnode, "reg", NULL); + reg = of_get_property(busnode, "reg", NULL); if (reg == NULL) continue; @@ -950,7 +950,8 @@ struct pmac_i2c_bus *pmac_i2c_find_bus(struct device_node *node) if (p == bus->busnode) { if (prev && bus->flags & pmac_i2c_multibus) { const u32 *reg; - reg = get_property(prev, "reg", NULL); + reg = of_get_property(prev, "reg", + NULL); if (!reg) continue; if (((*reg) >> 8) != bus->channel) @@ -971,7 +972,7 @@ EXPORT_SYMBOL_GPL(pmac_i2c_find_bus); u8 pmac_i2c_get_dev_addr(struct device_node *device) { - const u32 *reg = get_property(device, "reg", NULL); + const u32 *reg = of_get_property(device, "reg", NULL); if (reg == NULL) return 0; diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index 6fbac30..22c4ae4 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c @@ -70,11 +70,11 @@ static int __init fixup_one_level_bus_range(struct device_node *node, int higher int len; /* For PCI<->PCI bridges or CardBus bridges, we go down */ - class_code = get_property(node, "class-code", NULL); + class_code = of_get_property(node, "class-code", NULL); if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI && (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) continue; - 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[1] > higher) higher = bus_range[1]; @@ -100,7 +100,7 @@ static void __init fixup_bus_range(struct device_node *bridge) if (prop == NULL || prop->length < 2 * sizeof(int)) return; - bus_range = (int *)prop->value; + bus_range = prop->value; bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]); } @@ -246,8 +246,8 @@ static int chaos_validate_dev(struct pci_bus *bus, int devfn, int offset) if (np == NULL) return PCIBIOS_DEVICE_NOT_FOUND; - vendor = get_property(np, "vendor-id", NULL); - device = get_property(np, "device-id", NULL); + vendor = of_get_property(np, "vendor-id", NULL); + device = of_get_property(np, "device-id", NULL); if (vendor == NULL || device == NULL) return PCIBIOS_DEVICE_NOT_FOUND; @@ -622,13 +622,14 @@ static void __init init_p2pbridge(void) /* XXX it would be better here to identify the specific PCI-PCI bridge chip we have. */ - if ((p2pbridge = find_devices("pci-bridge")) == 0 + p2pbridge = of_find_node_by_name(NULL, "pci-bridge"); + if (p2pbridge == NULL || p2pbridge->parent == NULL || strcmp(p2pbridge->parent->name, "pci") != 0) - return; + goto done; if (pci_device_from_OF_node(p2pbridge, &bus, &devfn) < 0) { DBG("Can't find PCI infos for PCI<->PCI bridge\n"); - return; + goto done; } /* Warning: At this point, we have not yet renumbered all busses. * So we must use OF walking to find out hose @@ -636,16 +637,18 @@ static void __init init_p2pbridge(void) hose = pci_find_hose_for_OF_device(p2pbridge); if (!hose) { DBG("Can't find hose for PCI<->PCI bridge\n"); - return; + goto done; } if (early_read_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, &val) < 0) { printk(KERN_ERR "init_p2pbridge: couldn't read bridge" " control\n"); - return; + goto done; } val &= ~PCI_BRIDGE_CTL_MASTER_ABORT; early_write_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, val); +done: + of_node_put(p2pbridge); } static void __init init_second_ohare(void) @@ -691,17 +694,17 @@ static void __init fixup_nec_usb2(void) const u32 *prop; u8 bus, devfn; - prop = get_property(nec, "vendor-id", NULL); + prop = of_get_property(nec, "vendor-id", NULL); if (prop == NULL) continue; if (0x1033 != *prop) continue; - prop = get_property(nec, "device-id", NULL); + prop = of_get_property(nec, "device-id", NULL); if (prop == NULL) continue; if (0x0035 != *prop) continue; - prop = get_property(nec, "reg", NULL); + prop = of_get_property(nec, "reg", NULL); if (prop == NULL) continue; devfn = (prop[0] >> 8) & 0xff; @@ -909,7 +912,7 @@ static int __init add_bridge(struct device_node *dev) has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); /* Get bus range if any */ - 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)) { printk(KERN_WARNING "Can't get bus-range for %s, assume" " bus 0\n", dev->full_name); @@ -1199,8 +1202,7 @@ void __init pmac_pcibios_after_init(void) } #endif /* CONFIG_BLK_DEV_IDE */ - nd = find_devices("firewire"); - while (nd) { + for_each_node_by_name(nd, "firewire") { if (nd->parent && (device_is_compatible(nd, "pci106b,18") || device_is_compatible(nd, "pci106b,30") || device_is_compatible(nd, "pci11c1,5811")) @@ -1208,15 +1210,14 @@ void __init pmac_pcibios_after_init(void) pmac_call_feature(PMAC_FTR_1394_ENABLE, nd, 0, 0); pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, nd, 0, 0); } - nd = nd->next; } - nd = find_devices("ethernet"); - while (nd) { + of_node_put(nd); + for_each_node_by_name(nd, "ethernet") { if (nd->parent && device_is_compatible(nd, "gmac") && device_is_compatible(nd->parent, "uni-north")) pmac_call_feature(PMAC_FTR_GMAC_ENABLE, nd, 0, 0); - nd = nd->next; } + of_node_put(nd); } #ifdef CONFIG_PPC32 diff --git a/arch/powerpc/platforms/powermac/pfunc_base.c b/arch/powerpc/platforms/powermac/pfunc_base.c index 5c6c15c..45d54b9 100644 --- a/arch/powerpc/platforms/powermac/pfunc_base.c +++ b/arch/powerpc/platforms/powermac/pfunc_base.c @@ -114,7 +114,7 @@ static void macio_gpio_init_one(struct macio_chip *macio) * we just create them all */ for (gp = NULL; (gp = of_get_next_child(gparent, gp)) != NULL;) { - const u32 *reg = get_property(gp, "reg", NULL); + const u32 *reg = of_get_property(gp, "reg", NULL); unsigned long offset; if (reg == NULL) continue; diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c index 7651f278..85434231 100644 --- a/arch/powerpc/platforms/powermac/pfunc_core.c +++ b/arch/powerpc/platforms/powermac/pfunc_core.c @@ -692,8 +692,7 @@ static int pmf_add_functions(struct pmf_device *dev, void *driverdata) name = pp->name + plen; if (strlen(name) && pp->length >= 12) count += pmf_add_function_prop(dev, driverdata, name, - (u32 *)pp->value, - pp->length); + pp->value, pp->length); } return count; } @@ -821,7 +820,7 @@ struct pmf_function *__pmf_find_function(struct device_node *target, * one, then we fallback to a direct call attempt */ snprintf(fname, 63, "platform-%s", name); - prop = get_property(target, fname, NULL); + prop = of_get_property(target, fname, NULL); if (prop == NULL) goto find_it; ph = *prop; diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c index 5e5c0e4..ae5097a 100644 --- a/arch/powerpc/platforms/powermac/pic.c +++ b/arch/powerpc/platforms/powermac/pic.c @@ -482,14 +482,14 @@ static struct mpic * __init pmac_setup_one_mpic(struct device_node *np, pmac_call_feature(PMAC_FTR_ENABLE_MPIC, np, 0, 0); flags |= MPIC_WANTS_RESET; - if (get_property(np, "big-endian", NULL)) + if (of_get_property(np, "big-endian", NULL)) flags |= MPIC_BIG_ENDIAN; /* Primary Big Endian means HT interrupts. This is quite dodgy * but works until I find a better way */ if (master && (flags & MPIC_BIG_ENDIAN)) - flags |= MPIC_BROKEN_U3; + flags |= MPIC_U3_HT_IRQS; mpic = mpic_alloc(np, r.start, flags, 0, 0, name); if (mpic == NULL) @@ -510,7 +510,7 @@ static int __init pmac_pic_probe_mpic(void) for (np = NULL; (np = of_find_node_by_type(np, "open-pic")) != NULL;) { if (master == NULL && - get_property(np, "interrupts", NULL) == NULL) + of_get_property(np, "interrupts", NULL) == NULL) master = of_node_get(np); else if (slave == NULL) slave = of_node_get(np); @@ -575,7 +575,7 @@ void __init pmac_pic_init(void) #ifdef CONFIG_PPC32 if (!pmac_newworld) flags |= OF_IMAP_OLDWORLD_MAC; - if (get_property(of_chosen, "linux,bootx", NULL) != NULL) + if (of_get_property(of_chosen, "linux,bootx", NULL) != NULL) flags |= OF_IMAP_NO_PHANDLE; #endif /* CONFIG_PPC_32 */ diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 651fa42..b820cab 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -42,7 +42,6 @@ #include <linux/initrd.h> #include <linux/vt_kern.h> #include <linux/console.h> -#include <linux/ide.h> #include <linux/pci.h> #include <linux/adb.h> #include <linux/cuda.h> @@ -135,12 +134,12 @@ static void pmac_show_cpuinfo(struct seq_file *m) seq_printf(m, "machine\t\t: "); np = of_find_node_by_path("/"); if (np != NULL) { - pp = get_property(np, "model", NULL); + pp = of_get_property(np, "model", NULL); if (pp != NULL) seq_printf(m, "%s\n", pp); else seq_printf(m, "PowerMac\n"); - pp = get_property(np, "compatible", &plen); + pp = of_get_property(np, "compatible", &plen); if (pp != NULL) { seq_printf(m, "motherboard\t:"); while (plen > 0) { @@ -164,11 +163,13 @@ static void pmac_show_cpuinfo(struct seq_file *m) if (np == NULL) np = of_find_node_by_type(NULL, "cache"); if (np != NULL) { - const unsigned int *ic = get_property(np, "i-cache-size", NULL); - const unsigned int *dc = get_property(np, "d-cache-size", NULL); + const unsigned int *ic = + of_get_property(np, "i-cache-size", NULL); + const unsigned int *dc = + of_get_property(np, "d-cache-size", NULL); seq_printf(m, "L2 cache\t:"); has_l2cache = 1; - if (get_property(np, "cache-unified", NULL) != 0 && dc) { + if (of_get_property(np, "cache-unified", NULL) != 0 && dc) { seq_printf(m, " %dK unified", *dc / 1024); } else { if (ic) @@ -177,7 +178,7 @@ static void pmac_show_cpuinfo(struct seq_file *m) seq_printf(m, "%s %dK data", (ic? " +": ""), *dc / 1024); } - pp = get_property(np, "ram-type", NULL); + pp = of_get_property(np, "ram-type", NULL); if (pp) seq_printf(m, " %s", pp); seq_printf(m, "\n"); @@ -192,8 +193,11 @@ static void pmac_show_cpuinfo(struct seq_file *m) #ifndef CONFIG_ADB_CUDA int find_via_cuda(void) { - if (!find_devices("via-cuda")) + struct device_node *dn = of_find_node_by_name(NULL, "via-cuda"); + + if (!dn) return 0; + of_node_put(dn); printk("WARNING ! Your machine is CUDA-based but your kernel\n"); printk(" wasn't compiled with CONFIG_ADB_CUDA option !\n"); return 0; @@ -203,8 +207,11 @@ int find_via_cuda(void) #ifndef CONFIG_ADB_PMU int find_via_pmu(void) { - if (!find_devices("via-pmu")) + struct device_node *dn = of_find_node_by_name(NULL, "via-pmu"); + + if (!dn) return 0; + of_node_put(dn); printk("WARNING ! Your machine is PMU-based but your kernel\n"); printk(" wasn't compiled with CONFIG_ADB_PMU option !\n"); return 0; @@ -224,6 +231,8 @@ static volatile u32 *sysctrl_regs; static void __init ohare_init(void) { + struct device_node *dn; + /* this area has the CPU identification register and some registers used by smp boards */ sysctrl_regs = (volatile u32 *) ioremap(0xf8000000, 0x1000); @@ -233,7 +242,9 @@ static void __init ohare_init(void) * We assume that we have a PSX memory controller iff * we have an ohare I/O controller. */ - if (find_devices("ohare") != NULL) { + dn = of_find_node_by_name(NULL, "ohare"); + if (dn) { + of_node_put(dn); if (((sysctrl_regs[2] >> 24) & 0xf) >= 3) { if (sysctrl_regs[4] & 0x10) sysctrl_regs[4] |= 0x04000020; @@ -249,18 +260,19 @@ static void __init l2cr_init(void) { /* Checks "l2cr-value" property in the registry */ if (cpu_has_feature(CPU_FTR_L2CR)) { - struct device_node *np = find_devices("cpus"); + struct device_node *np = of_find_node_by_name(NULL, "cpus"); if (np == 0) - np = find_type_devices("cpu"); + np = of_find_node_by_type(NULL, "cpu"); if (np != 0) { const unsigned int *l2cr = - get_property(np, "l2cr-value", NULL); + of_get_property(np, "l2cr-value", NULL); if (l2cr != 0) { ppc_override_l2cr = 1; ppc_override_l2cr_value = *l2cr; _set_L2CR(0); _set_L2CR(ppc_override_l2cr_value); } + of_node_put(np); } } @@ -286,7 +298,7 @@ static void __init pmac_setup_arch(void) loops_per_jiffy = 50000000 / HZ; cpu = of_find_node_by_type(NULL, "cpu"); if (cpu != NULL) { - fp = get_property(cpu, "clock-frequency", NULL); + fp = of_get_property(cpu, "clock-frequency", NULL); if (fp != NULL) { if (pvr >= 0x30 && pvr < 0x80) /* PPC970 etc. */ @@ -303,7 +315,7 @@ static void __init pmac_setup_arch(void) /* See if newworld or oldworld */ for (ic = NULL; (ic = of_find_all_nodes(ic)) != NULL; ) - if (get_property(ic, "interrupt-controller", NULL)) + if (of_get_property(ic, "interrupt-controller", NULL)) break; if (ic) { pmac_newworld = 1; @@ -341,8 +353,15 @@ static void __init pmac_setup_arch(void) #ifdef CONFIG_SMP /* Check for Core99 */ - if (find_devices("uni-n") || find_devices("u3") || find_devices("u4")) + ic = of_find_node_by_name(NULL, "uni-n"); + if (!ic) + ic = of_find_node_by_name(NULL, "u3"); + if (!ic) + ic = of_find_node_by_name(NULL, "u4"); + if (ic) { + of_node_put(ic); smp_ops = &core99_smp_ops; + } #ifdef CONFIG_PPC32 else smp_ops = &psurge_smp_ops; @@ -616,15 +635,6 @@ static void __init pmac_init_early(void) #endif } -/* - * pmac has no legacy IO, anything calling this function has to - * fail or bad things will happen - */ -static int pmac_check_legacy_ioport(unsigned int baseport) -{ - return -ENODEV; -} - static int __init pmac_declare_of_platform_devices(void) { struct device_node *np; @@ -736,7 +746,6 @@ define_machine(powermac) { .get_rtc_time = pmac_get_rtc_time, .calibrate_decr = pmac_calibrate_decr, .feature_call = pmac_do_feature_call, - .check_legacy_ioport = pmac_check_legacy_ioport, .progress = udbg_progress, #ifdef CONFIG_PPC64 .pci_probe_mode = pmac_pci_probe_mode, diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index d73fb73..6f32c4e 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c @@ -264,6 +264,7 @@ static void __init psurge_quad_init(void) static int __init smp_psurge_probe(void) { int i, ncpus; + struct device_node *dn; /* We don't do SMP on the PPC601 -- paulus */ if (PVR_VER(mfspr(SPRN_PVR)) == 1) @@ -279,8 +280,10 @@ static int __init smp_psurge_probe(void) * in the hammerhead memory controller in the case of the * dual-cpu powersurge board. -- paulus. */ - if (find_devices("hammerhead") == NULL) + dn = of_find_node_by_name(NULL, "hammerhead"); + if (dn == NULL) return 1; + of_node_put(dn); hhead_base = ioremap(HAMMERHEAD_BASE, 0x800); quad_base = ioremap(PSURGE_QUAD_REG_ADDR, 1024); @@ -567,7 +570,7 @@ static void __init smp_core99_setup_i2c_hwsync(int ncpus) pmac_tb_clock_chip_host = pmac_i2c_find_bus(cc); if (pmac_tb_clock_chip_host == NULL) continue; - reg = get_property(cc, "reg", NULL); + reg = of_get_property(cc, "reg", NULL); if (reg == NULL) continue; switch (*reg) { @@ -695,7 +698,7 @@ static void __init smp_core99_setup(int ncpus) struct device_node *cpus = of_find_node_by_path("/cpus"); if (cpus && - get_property(cpus, "platform-cpu-timebase", NULL)) { + of_get_property(cpus, "platform-cpu-timebase", NULL)) { pmac_tb_freeze = smp_core99_pfunc_tb_freeze; printk(KERN_INFO "Processor timebase sync using" " platform function\n"); @@ -712,7 +715,7 @@ static void __init smp_core99_setup(int ncpus) core99_tb_gpio = KL_GPIO_TB_ENABLE; /* default value */ cpu = of_find_node_by_type(NULL, "cpu"); if (cpu != NULL) { - tbprop = get_property(cpu, "timebase-enable", NULL); + tbprop = of_get_property(cpu, "timebase-enable", NULL); if (tbprop) core99_tb_gpio = *tbprop; of_node_put(cpu); diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c index a417390..bf9da56 100644 --- a/arch/powerpc/platforms/powermac/time.c +++ b/arch/powerpc/platforms/powermac/time.c @@ -297,49 +297,11 @@ int __init via_calibrate_decr(void) } #endif -#ifdef CONFIG_PM -/* - * Reset the time after a sleep. - */ -static int -time_sleep_notify(struct pmu_sleep_notifier *self, int when) -{ - static unsigned long time_diff; - unsigned long flags; - unsigned long seq; - struct timespec tv; - - switch (when) { - case PBOOK_SLEEP_NOW: - do { - seq = read_seqbegin_irqsave(&xtime_lock, flags); - time_diff = xtime.tv_sec - pmac_get_boot_time(); - } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); - break; - case PBOOK_WAKE: - tv.tv_sec = pmac_get_boot_time() + time_diff; - tv.tv_nsec = 0; - do_settimeofday(&tv); - break; - } - return PBOOK_SLEEP_OK; -} - -static struct pmu_sleep_notifier time_sleep_notifier = { - time_sleep_notify, SLEEP_LEVEL_MISC, -}; -#endif /* CONFIG_PM */ - /* * Query the OF and get the decr frequency. */ void __init pmac_calibrate_decr(void) { -#if defined(CONFIG_PM) && defined(CONFIG_ADB_PMU) - /* XXX why here? */ - pmu_register_sleep_notifier(&time_sleep_notifier); -#endif - generic_calibrate_decr(); #ifdef CONFIG_PPC32 diff --git a/arch/powerpc/platforms/powermac/udbg_scc.c b/arch/powerpc/platforms/powermac/udbg_scc.c index 379db05..47de4d3 100644 --- a/arch/powerpc/platforms/powermac/udbg_scc.c +++ b/arch/powerpc/platforms/powermac/udbg_scc.c @@ -81,7 +81,7 @@ void udbg_scc_init(int force_scc) macio = of_get_parent(escc); if (macio == NULL) goto bail; - path = get_property(of_chosen, "linux,stdout-path", NULL); + path = of_get_property(of_chosen, "linux,stdout-path", NULL); if (path != NULL) stdout = of_find_node_by_path(path); for (ch = NULL; (ch = of_get_next_child(escc, ch)) != NULL;) { @@ -96,13 +96,13 @@ void udbg_scc_init(int force_scc) ch = ch_def ? ch_def : ch_a; /* Get address within mac-io ASIC */ - reg = get_property(escc, "reg", NULL); + reg = of_get_property(escc, "reg", NULL); if (reg == NULL) goto bail; addr = reg[0]; /* Get address of mac-io PCI itself */ - reg = get_property(macio, "assigned-addresses", NULL); + reg = of_get_property(macio, "assigned-addresses", NULL); if (reg == NULL) goto bail; addr += reg[2]; diff --git a/arch/powerpc/platforms/prep/Kconfig b/arch/powerpc/platforms/prep/Kconfig index 673ac47..29d4112 100644 --- a/arch/powerpc/platforms/prep/Kconfig +++ b/arch/powerpc/platforms/prep/Kconfig @@ -1,3 +1,12 @@ +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 PREP_RESIDUAL bool "Support for PReP Residual Data" diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig index 1a481a6..40f0008 100644 --- a/arch/powerpc/platforms/ps3/Kconfig +++ b/arch/powerpc/platforms/ps3/Kconfig @@ -1,3 +1,19 @@ +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. + menu "PS3 Platform Options" depends on PPC_PS3 diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c index e12e59f..ea60c45 100644 --- a/arch/powerpc/platforms/ps3/htab.c +++ b/arch/powerpc/platforms/ps3/htab.c @@ -39,7 +39,7 @@ static unsigned long htab_addr; static unsigned char *bolttab; static unsigned char *inusetab; -static spinlock_t ps3_bolttab_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(ps3_bolttab_lock); #define debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g) \ _debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__) diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index a57032c..16e4e40 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig @@ -1,3 +1,13 @@ +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_SPLPAR depends on PPC_PSERIES diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 2dfd050..90235d5 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile @@ -2,14 +2,15 @@ ifeq ($(CONFIG_PPC64),y) EXTRA_CFLAGS += -mno-minimal-toc endif -obj-y := pci.o lpar.o hvCall.o nvram.o reconfig.o \ - setup.o iommu.o ras.o rtasd.o pci_dlpar.o \ +obj-y := lpar.o hvCall.o nvram.o reconfig.o \ + setup.o iommu.o ras.o rtasd.o \ firmware.o power.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_XICS) += xics.o obj-$(CONFIG_SCANLOG) += scanlog.o obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o obj-$(CONFIG_KEXEC) += kexec.o +obj-$(CONFIG_PCI) += pci.o pci_dlpar.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug-cpu.o diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index 6cedbc0..48fbd44 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c @@ -74,7 +74,10 @@ * is broken and panic. This sets the threshold for how many read * attempts we allow before panicking. */ -#define EEH_MAX_FAILS 100000 +#define EEH_MAX_FAILS 2100000 + +/* Time to wait for a PCI slot to retport status, in milliseconds */ +#define PCI_BUS_RESET_WAIT_MSEC (60*1000) /* RTAS tokens */ static int ibm_set_eeh_option; @@ -83,6 +86,7 @@ static int ibm_read_slot_reset_state; static int ibm_read_slot_reset_state2; static int ibm_slot_error_detail; static int ibm_get_config_addr_info; +static int ibm_get_config_addr_info2; static int ibm_configure_bridge; int eeh_subsystem_enabled; @@ -168,6 +172,55 @@ static int read_slot_reset_state(struct pci_dn *pdn, int rets[]) } /** + * eeh_wait_for_slot_status - returns error status of slot + * @pdn pci device node + * @max_wait_msecs maximum number to millisecs to wait + * + * Return negative value if a permanent error, else return + * Partition Endpoint (PE) status value. + * + * If @max_wait_msecs is positive, then this routine will + * sleep until a valid status can be obtained, or until + * the max allowed wait time is exceeded, in which case + * a -2 is returned. + */ +int +eeh_wait_for_slot_status(struct pci_dn *pdn, int max_wait_msecs) +{ + int rc; + int rets[3]; + int mwait; + + while (1) { + rc = read_slot_reset_state(pdn, rets); + if (rc) return rc; + if (rets[1] == 0) return -1; /* EEH is not supported */ + + if (rets[0] != 5) return rets[0]; /* return actual status */ + + if (rets[2] == 0) return -1; /* permanently unavailable */ + + if (max_wait_msecs <= 0) return -1; + + mwait = rets[2]; + if (mwait <= 0) { + printk (KERN_WARNING + "EEH: Firmware returned bad wait value=%d\n", mwait); + mwait = 1000; + } else if (mwait > 300*1000) { + printk (KERN_WARNING + "EEH: Firmware is taking too long, time=%d\n", mwait); + mwait = 300*1000; + } + max_wait_msecs -= mwait; + msleep (mwait); + } + + printk(KERN_WARNING "EEH: Timed out waiting for slot status\n"); + return -2; +} + +/** * eeh_token_to_phys - convert EEH address token to phys address * @token i/o token, should be address in the form 0xA.... */ @@ -229,7 +282,7 @@ void eeh_mark_slot (struct device_node *dn, int mode_flag) dn = find_device_pe (dn); /* Back up one, since config addrs might be shared */ - if (PCI_DN(dn) && PCI_DN(dn)->eeh_pe_config_addr) + if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent)) dn = dn->parent; PCI_DN(dn)->eeh_mode |= mode_flag; @@ -263,7 +316,7 @@ void eeh_clear_slot (struct device_node *dn, int mode_flag) dn = find_device_pe (dn); /* Back up one, since config addrs might be shared */ - if (PCI_DN(dn) && PCI_DN(dn)->eeh_pe_config_addr) + if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent)) dn = dn->parent; PCI_DN(dn)->eeh_mode &= ~mode_flag; @@ -293,7 +346,6 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) int rets[3]; unsigned long flags; struct pci_dn *pdn; - enum pci_channel_state state; int rc = 0; total_mmio_ffs++; @@ -367,25 +419,25 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) goto dn_unlock; } - /* If EEH is not supported on this device, punt. */ - if (rets[1] != 1) { - printk(KERN_WARNING "EEH: event on unsupported device, rc=%d dn=%s\n", - ret, dn->full_name); + /* Note that config-io to empty slots may fail; + * they are empty when they don't have children. */ + if ((rets[0] == 5) && (dn->child == NULL)) { false_positives++; rc = 0; goto dn_unlock; } - /* If not the kind of error we know about, punt. */ - if (rets[0] != 2 && rets[0] != 4 && rets[0] != 5) { + /* If EEH is not supported on this device, punt. */ + if (rets[1] != 1) { + printk(KERN_WARNING "EEH: event on unsupported device, rc=%d dn=%s\n", + ret, dn->full_name); false_positives++; rc = 0; goto dn_unlock; } - /* Note that config-io to empty slots may fail; - * we recognize empty because they don't have children. */ - if ((rets[0] == 5) && (dn->child == NULL)) { + /* If not the kind of error we know about, punt. */ + if (rets[0] != 1 && rets[0] != 2 && rets[0] != 4 && rets[0] != 5) { false_positives++; rc = 0; goto dn_unlock; @@ -399,17 +451,12 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) eeh_mark_slot (dn, EEH_MODE_ISOLATED); spin_unlock_irqrestore(&confirm_error_lock, flags); - state = pci_channel_io_normal; - if ((rets[0] == 2) || (rets[0] == 4)) - state = pci_channel_io_frozen; - if (rets[0] == 5) - state = pci_channel_io_perm_failure; - eeh_send_failure_event (dn, dev, state, rets[2]); + eeh_send_failure_event (dn, dev); /* Most EEH events are due to device driver bugs. Having * a stack trace will help the device-driver authors figure * out what happened. So print that out. */ - if (rets[0] != 5) dump_stack(); + dump_stack(); return 1; dn_unlock: @@ -458,38 +505,6 @@ EXPORT_SYMBOL(eeh_check_failure); /* The code below deals with error recovery */ /** - * eeh_slot_availability - returns error status of slot - * @pdn pci device node - * - * Return negative value if a permanent error, else return - * a number of milliseconds to wait until the PCI slot is - * ready to be used. - */ -static int -eeh_slot_availability(struct pci_dn *pdn) -{ - int rc; - int rets[3]; - - rc = read_slot_reset_state(pdn, rets); - - if (rc) return rc; - - if (rets[1] == 0) return -1; /* EEH is not supported */ - if (rets[0] == 0) return 0; /* Oll Korrect */ - if (rets[0] == 5) { - if (rets[2] == 0) return -1; /* permanently unavailable */ - return rets[2]; /* number of millisecs to wait */ - } - if (rets[0] == 1) - return 250; - - printk (KERN_ERR "EEH: Slot unavailable: rc=%d, rets=%d %d %d\n", - rc, rets[0], rets[1], rets[2]); - return -2; -} - -/** * rtas_pci_enable - enable MMIO or DMA transfers for this slot * @pdn pci device node */ @@ -512,9 +527,13 @@ rtas_pci_enable(struct pci_dn *pdn, int function) function); if (rc) - printk(KERN_WARNING "EEH: Cannot enable function %d, err=%d dn=%s\n", + printk(KERN_WARNING "EEH: Unexpected state change %d, err=%d dn=%s\n", function, rc, pdn->node->full_name); + rc = eeh_wait_for_slot_status (pdn, PCI_BUS_RESET_WAIT_MSEC); + if ((rc == 4) && (function == EEH_THAW_MMIO)) + return 0; + return rc; } @@ -595,36 +614,24 @@ int rtas_set_slot_reset(struct pci_dn *pdn) { int i, rc; - __rtas_set_slot_reset(pdn); + /* Take three shots at resetting the bus */ + for (i=0; i<3; i++) { + __rtas_set_slot_reset(pdn); - /* Now double check with the firmware to make sure the device is - * ready to be used; if not, wait for recovery. */ - for (i=0; i<10; i++) { - rc = eeh_slot_availability (pdn); + rc = eeh_wait_for_slot_status(pdn, PCI_BUS_RESET_WAIT_MSEC); if (rc == 0) return 0; - if (rc == -2) { - printk (KERN_ERR "EEH: failed (%d) to reset slot %s\n", - i, pdn->node->full_name); - __rtas_set_slot_reset(pdn); - continue; - } - if (rc < 0) { printk (KERN_ERR "EEH: unrecoverable slot failure %s\n", pdn->node->full_name); return -1; } - - msleep (rc+100); + printk (KERN_ERR "EEH: bus reset %d failed on slot %s\n", + i+1, pdn->node->full_name); } - rc = eeh_slot_availability (pdn); - if (rc) - printk (KERN_ERR "EEH: timeout resetting slot %s\n", pdn->node->full_name); - - return rc; + return -1; } /* ------------------------------------------------------- */ @@ -744,16 +751,48 @@ struct eeh_early_enable_info { unsigned int buid_lo; }; +static int get_pe_addr (int config_addr, + struct eeh_early_enable_info *info) +{ + unsigned int rets[3]; + int ret; + + /* Use latest config-addr token on power6 */ + if (ibm_get_config_addr_info2 != RTAS_UNKNOWN_SERVICE) { + /* Make sure we have a PE in hand */ + ret = rtas_call (ibm_get_config_addr_info2, 4, 2, rets, + config_addr, info->buid_hi, info->buid_lo, 1); + if (ret || (rets[0]==0)) + return 0; + + ret = rtas_call (ibm_get_config_addr_info2, 4, 2, rets, + config_addr, info->buid_hi, info->buid_lo, 0); + if (ret) + return 0; + return rets[0]; + } + + /* Use older config-addr token on power5 */ + if (ibm_get_config_addr_info != RTAS_UNKNOWN_SERVICE) { + ret = rtas_call (ibm_get_config_addr_info, 4, 2, rets, + config_addr, info->buid_hi, info->buid_lo, 0); + if (ret) + return 0; + return rets[0]; + } + return 0; +} + /* Enable eeh for the given device node. */ static void *early_enable_eeh(struct device_node *dn, void *data) { unsigned int rets[3]; struct eeh_early_enable_info *info = data; int ret; - const char *status = get_property(dn, "status", NULL); - const u32 *class_code = get_property(dn, "class-code", NULL); - const u32 *vendor_id = get_property(dn, "vendor-id", NULL); - const u32 *device_id = get_property(dn, "device-id", NULL); + const char *status = of_get_property(dn, "status", NULL); + const u32 *class_code = of_get_property(dn, "class-code", NULL); + const u32 *vendor_id = of_get_property(dn, "vendor-id", NULL); + const u32 *device_id = of_get_property(dn, "device-id", NULL); const u32 *regs; int enable; struct pci_dn *pdn = PCI_DN(dn); @@ -796,7 +835,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data) /* Ok... see if this device supports EEH. Some do, some don't, * and the only way to find out is to check each and every one. */ - regs = get_property(dn, "reg", NULL); + regs = of_get_property(dn, "reg", NULL); if (regs) { /* First register entry is addr (00BBSS00) */ /* Try to enable eeh */ @@ -810,15 +849,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data) /* If the newer, better, ibm,get-config-addr-info is supported, * then use that instead. */ - pdn->eeh_pe_config_addr = 0; - if (ibm_get_config_addr_info != RTAS_UNKNOWN_SERVICE) { - ret = rtas_call (ibm_get_config_addr_info, 4, 2, rets, - pdn->eeh_config_addr, - info->buid_hi, info->buid_lo, - 0); - if (ret == 0) - pdn->eeh_pe_config_addr = rets[0]; - } + pdn->eeh_pe_config_addr = get_pe_addr(pdn->eeh_config_addr, info); /* Some older systems (Power4) allow the * ibm,set-eeh-option call to succeed even on nodes @@ -889,6 +920,7 @@ void __init eeh_init(void) ibm_read_slot_reset_state = rtas_token("ibm,read-slot-reset-state"); ibm_slot_error_detail = rtas_token("ibm,slot-error-detail"); ibm_get_config_addr_info = rtas_token("ibm,get-config-addr-info"); + ibm_get_config_addr_info2 = rtas_token("ibm,get-config-addr-info2"); ibm_configure_bridge = rtas_token ("ibm,configure-bridge"); if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE) diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c index a4c0bf8..3170e00 100644 --- a/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/arch/powerpc/platforms/pseries/eeh_driver.c @@ -158,7 +158,8 @@ static void eeh_report_reset(struct pci_dev *dev, void *userdata) return; rc = driver->err_handler->slot_reset(dev); - if (*res == PCI_ERS_RESULT_NONE) *res = rc; + if ((*res == PCI_ERS_RESULT_NONE) || + (*res == PCI_ERS_RESULT_RECOVERED)) *res = rc; if (*res == PCI_ERS_RESULT_DISCONNECT && rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; } @@ -248,6 +249,7 @@ static void eeh_report_failure(struct pci_dev *dev, void *userdata) static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus) { + struct device_node *dn; int cnt, rc; /* pcibios will clear the counter; save the value */ @@ -263,23 +265,20 @@ static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus) if (rc) return rc; - /* New-style config addrs might be shared across multiple devices, - * Walk over all functions on this device */ - if (pe_dn->eeh_pe_config_addr) { - struct device_node *pe = pe_dn->node; - pe = pe->parent->child; - while (pe) { - struct pci_dn *ppe = PCI_DN(pe); - if (pe_dn->eeh_pe_config_addr == ppe->eeh_pe_config_addr) { - rtas_configure_bridge(ppe); - eeh_restore_bars(ppe); - } - pe = pe->sibling; + /* Walk over all functions on this device. */ + dn = pe_dn->node; + if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent)) + dn = dn->parent->child; + + while (dn) { + struct pci_dn *ppe = PCI_DN(dn); + /* On Power4, always true because eeh_pe_config_addr=0 */ + if (pe_dn->eeh_pe_config_addr == ppe->eeh_pe_config_addr) { + rtas_configure_bridge(ppe); + eeh_restore_bars(ppe); } - } else { - rtas_configure_bridge(pe_dn); - eeh_restore_bars(pe_dn); - } + dn = dn->sibling; + } /* Give the system 5 seconds to finish running the user-space * hotplug shutdown scripts, e.g. ifdown for ethernet. Yes, @@ -299,7 +298,7 @@ static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus) /* The longest amount of time to wait for a pci device * to come back on line, in seconds. */ -#define MAX_WAIT_FOR_RECOVERY 15 +#define MAX_WAIT_FOR_RECOVERY 150 struct pci_dn * handle_eeh_events (struct eeh_event *event) { @@ -315,14 +314,14 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event) if (!frozen_dn) { - location = get_property(event->dn, "ibm,loc-code", NULL); + location = of_get_property(event->dn, "ibm,loc-code", NULL); location = location ? location : "unknown"; printk(KERN_ERR "EEH: Error: Cannot find partition endpoint " "for location=%s pci addr=%s\n", location, pci_name(event->dev)); return NULL; } - location = get_property(frozen_dn, "ibm,loc-code", NULL); + location = of_get_property(frozen_dn, "ibm,loc-code", NULL); location = location ? location : "unknown"; /* There are two different styles for coming up with the PE. @@ -341,13 +340,6 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event) return NULL; } -#if 0 - /* We may get "permanent failure" messages on empty slots. - * These are false alarms. Empty slots have no child dn. */ - if ((event->state == pci_channel_io_perm_failure) && (frozen_device == NULL)) - return; -#endif - frozen_pdn = PCI_DN(frozen_dn); frozen_pdn->eeh_freeze_count++; @@ -362,13 +354,12 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event) if (frozen_pdn->eeh_freeze_count > EEH_MAX_ALLOWED_FREEZES) goto excess_failures; - /* If the reset state is a '5' and the time to reset is 0 (infinity) - * or is more then 15 seconds, then mark this as a permanent failure. - */ - if ((event->state == pci_channel_io_perm_failure) && - ((event->time_unavail <= 0) || - (event->time_unavail > MAX_WAIT_FOR_RECOVERY*1000))) + /* Get the current PCI slot state. */ + rc = eeh_wait_for_slot_status (frozen_pdn, MAX_WAIT_FOR_RECOVERY*1000); + if (rc < 0) { + printk(KERN_WARNING "EEH: Permanent failure\n"); goto hard_fail; + } eeh_slot_error_detail(frozen_pdn, 1 /* Temporary Error */); printk(KERN_WARNING @@ -390,14 +381,18 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event) */ if (result == PCI_ERS_RESULT_NONE) { rc = eeh_reset_device(frozen_pdn, frozen_bus); - if (rc) + if (rc) { + printk(KERN_WARNING "EEH: Unable to reset, rc=%d\n", rc); goto hard_fail; + } } /* If all devices reported they can proceed, then re-enable MMIO */ if (result == PCI_ERS_RESULT_CAN_RECOVER) { rc = rtas_pci_enable(frozen_pdn, EEH_THAW_MMIO); + if (rc < 0) + goto hard_fail; if (rc) { result = PCI_ERS_RESULT_NEED_RESET; } else { @@ -410,6 +405,8 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event) if (result == PCI_ERS_RESULT_CAN_RECOVER) { rc = rtas_pci_enable(frozen_pdn, EEH_THAW_DMA); + if (rc < 0) + goto hard_fail; if (rc) result = PCI_ERS_RESULT_NEED_RESET; else @@ -417,21 +414,28 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event) } /* If any device has a hard failure, then shut off everything. */ - if (result == PCI_ERS_RESULT_DISCONNECT) + if (result == PCI_ERS_RESULT_DISCONNECT) { + printk(KERN_WARNING "EEH: Device driver gave up\n"); goto hard_fail; + } /* If any device called out for a reset, then reset the slot */ if (result == PCI_ERS_RESULT_NEED_RESET) { rc = eeh_reset_device(frozen_pdn, NULL); - if (rc) + if (rc) { + printk(KERN_WARNING "EEH: Cannot reset, rc=%d\n", rc); goto hard_fail; + } result = PCI_ERS_RESULT_NONE; pci_walk_bus(frozen_bus, eeh_report_reset, &result); } /* All devices should claim they have recovered by now. */ - if (result != PCI_ERS_RESULT_RECOVERED) + if ((result != PCI_ERS_RESULT_RECOVERED) && + (result != PCI_ERS_RESULT_NONE)) { + printk(KERN_WARNING "EEH: Not recovered\n"); goto hard_fail; + } /* Tell all device drivers that they can resume operations */ pci_walk_bus(frozen_bus, eeh_report_resume, NULL); diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c index 49037ed..ddb80f5 100644 --- a/arch/powerpc/platforms/pseries/eeh_event.c +++ b/arch/powerpc/platforms/pseries/eeh_event.c @@ -118,9 +118,7 @@ static void eeh_thread_launcher(struct work_struct *dummy) * (from a workqueue). */ int eeh_send_failure_event (struct device_node *dn, - struct pci_dev *dev, - enum pci_channel_state state, - int time_unavail) + struct pci_dev *dev) { unsigned long flags; struct eeh_event *event; @@ -128,7 +126,7 @@ int eeh_send_failure_event (struct device_node *dn, if (!mem_init_done) { printk(KERN_ERR "EEH: event during early boot not handled\n"); - location = get_property(dn, "ibm,loc-code", NULL); + location = of_get_property(dn, "ibm,loc-code", NULL); printk(KERN_ERR "EEH: device node = %s\n", dn->full_name); printk(KERN_ERR "EEH: PCI location = %s\n", location); return 1; @@ -144,8 +142,6 @@ int eeh_send_failure_event (struct device_node *dn, event->dn = dn; event->dev = dev; - event->state = state; - event->time_unavail = time_unavail; /* We may or may not be called in an interrupt context */ spin_lock_irqsave(&eeh_eventlist_lock, flags); diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c index 90522e3..29bf83b 100644 --- a/arch/powerpc/platforms/pseries/firmware.c +++ b/arch/powerpc/platforms/pseries/firmware.c @@ -80,7 +80,7 @@ void __init fw_feature_init(void) goto out; } - hypertas = get_property(dn, "ibm,hypertas-functions", &len); + hypertas = of_get_property(dn, "ibm,hypertas-functions", &len); if (hypertas == NULL) goto out; diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c index f460b9c..9711eb0 100644 --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c @@ -143,7 +143,7 @@ static int pseries_add_processor(struct device_node *np) int err = -ENOSPC, len, nthreads, i; const u32 *intserv; - intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len); + intserv = of_get_property(np, "ibm,ppc-interrupt-server#s", &len); if (!intserv) return 0; @@ -203,7 +203,7 @@ static void pseries_remove_processor(struct device_node *np) int len, nthreads, i; const u32 *intserv; - intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len); + intserv = of_get_property(np, "ibm,ppc-interrupt-server#s", &len); if (!intserv) return; diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index e6653a8..66665c8 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -242,6 +242,7 @@ static unsigned long tce_get_pSeriesLP(struct iommu_table *tbl, long tcenum) return tce_ret; } +#ifdef CONFIG_PCI static void iommu_table_setparms(struct pci_controller *phb, struct device_node *dn, struct iommu_table *tbl) @@ -252,8 +253,8 @@ static void iommu_table_setparms(struct pci_controller *phb, node = (struct device_node *)phb->arch_data; - basep = get_property(node, "linux,tce-base", NULL); - sizep = get_property(node, "linux,tce-size", NULL); + basep = of_get_property(node, "linux,tce-base", NULL); + sizep = of_get_property(node, "linux,tce-size", NULL); if (basep == NULL || sizep == NULL) { printk(KERN_ERR "PCI_DMA: iommu_table_setparms: %s has " "missing tce entries !\n", dn->full_name); @@ -403,7 +404,7 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus) /* Find nearest ibm,dma-window, walking up the device tree */ for (pdn = dn; pdn != NULL; pdn = pdn->parent) { - dma_window = get_property(pdn, "ibm,dma-window", NULL); + dma_window = of_get_property(pdn, "ibm,dma-window", NULL); if (dma_window != NULL) break; } @@ -478,29 +479,6 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev) pci_name(dev)); } -static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node) -{ - int err = NOTIFY_OK; - struct device_node *np = node; - struct pci_dn *pci = PCI_DN(np); - - switch (action) { - case PSERIES_RECONFIG_REMOVE: - if (pci && pci->iommu_table && - get_property(np, "ibm,dma-window", NULL)) - iommu_free_table(np); - break; - default: - err = NOTIFY_DONE; - break; - } - return err; -} - -static struct notifier_block iommu_reconfig_nb = { - .notifier_call = iommu_reconfig_notifier, -}; - static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) { struct device_node *pdn, *dn; @@ -521,7 +499,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table; pdn = pdn->parent) { - dma_window = get_property(pdn, "ibm,dma-window", NULL); + dma_window = of_get_property(pdn, "ibm,dma-window", NULL); if (dma_window) break; } @@ -554,15 +532,44 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) dev->dev.archdata.dma_data = pci->iommu_table; } +#else /* CONFIG_PCI */ +#define pci_dma_bus_setup_pSeries NULL +#define pci_dma_dev_setup_pSeries NULL +#define pci_dma_bus_setup_pSeriesLP NULL +#define pci_dma_dev_setup_pSeriesLP NULL +#endif /* !CONFIG_PCI */ + +static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node) +{ + int err = NOTIFY_OK; + struct device_node *np = node; + struct pci_dn *pci = PCI_DN(np); + + switch (action) { + case PSERIES_RECONFIG_REMOVE: + if (pci && pci->iommu_table && + of_get_property(np, "ibm,dma-window", NULL)) + iommu_free_table(np); + break; + default: + err = NOTIFY_DONE; + break; + } + return err; +} + +static struct notifier_block iommu_reconfig_nb = { + .notifier_call = iommu_reconfig_notifier, +}; /* These are called very early. */ void iommu_init_early_pSeries(void) { - if (of_chosen && get_property(of_chosen, "linux,iommu-off", NULL)) { + if (of_chosen && of_get_property(of_chosen, "linux,iommu-off", NULL)) { /* Direct I/O, IOMMU off */ ppc_md.pci_dma_dev_setup = NULL; ppc_md.pci_dma_bus_setup = NULL; - pci_dma_ops = &dma_direct_ops; + set_pci_dma_ops(&dma_direct_ops); return; } @@ -588,6 +595,6 @@ void iommu_init_early_pSeries(void) pSeries_reconfig_notifier_register(&iommu_reconfig_nb); - pci_dma_ops = &dma_iommu_ops; + set_pci_dma_ops(&dma_iommu_ops); } diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 843ee96..3a70e8a 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -209,13 +209,13 @@ void __init find_udbg_vterm(void) /* find the boot console from /chosen/stdout */ if (!of_chosen) return; - name = get_property(of_chosen, "linux,stdout-path", NULL); + name = of_get_property(of_chosen, "linux,stdout-path", NULL); if (name == NULL) return; stdout_node = of_find_node_by_path(name); if (!stdout_node) return; - name = get_property(stdout_node, "name", NULL); + name = of_get_property(stdout_node, "name", NULL); if (!name) { printk(KERN_WARNING "stdout node missing 'name' property!\n"); goto out; @@ -226,7 +226,7 @@ void __init find_udbg_vterm(void) /* Check if it's a virtual terminal */ if (strncmp(name, "vty", 3) != 0) goto out; - termno = get_property(stdout_node, "reg", NULL); + termno = of_get_property(stdout_node, "reg", NULL); if (termno == NULL) goto out; vtermno = termno[0]; diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c index 64163ce..f68903e 100644 --- a/arch/powerpc/platforms/pseries/nvram.c +++ b/arch/powerpc/platforms/pseries/nvram.c @@ -130,7 +130,7 @@ int __init pSeries_nvram_init(void) if (nvram == NULL) return -ENODEV; - nbytes_p = get_property(nvram, "#bytes", &proplen); + nbytes_p = of_get_property(nvram, "#bytes", &proplen); if (nbytes_p == NULL || proplen != sizeof(unsigned int)) return -EIO; diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c index fa59124..2c6ded2 100644 --- a/arch/powerpc/platforms/pseries/pci.c +++ b/arch/powerpc/platforms/pseries/pci.c @@ -25,6 +25,7 @@ #include <linux/pci.h> #include <linux/string.h> +#include <asm/eeh.h> #include <asm/pci-bridge.h> #include <asm/prom.h> #include <asm/ppc-pci.h> @@ -39,7 +40,7 @@ void pcibios_name_device(struct pci_dev *dev) */ dn = pci_device_to_OF_node(dev); if (dn) { - char *loc_code = get_property(dn, "ibm,loc-code", 0); + const char *loc_code = of_get_property(dn, "ibm,loc-code", 0); if (loc_code) { int loc_len = strlen(loc_code); if (loc_len < sizeof(dev->dev.name)) { diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c index ac56b86..fdc1a36 100644 --- a/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c @@ -29,6 +29,7 @@ #include <asm/pci-bridge.h> #include <asm/ppc-pci.h> #include <asm/firmware.h> +#include <asm/eeh.h> static struct pci_bus * find_bus_among_children(struct pci_bus *bus, diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c index edc0388..53aa041 100644 --- a/arch/powerpc/platforms/pseries/ras.c +++ b/arch/powerpc/platforms/pseries/ras.c @@ -85,7 +85,7 @@ static void request_ras_irqs(struct device_node *np, * map those interrupts using the default interrupt host and default * trigger */ - opicprop = get_property(np, "open-pic-interrupt", &opicplen); + opicprop = of_get_property(np, "open-pic-interrupt", &opicplen); if (opicprop) { opicplen /= sizeof(u32); for (i = 0; i < opicplen; i++) { diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c index 77d0937..9797b10 100644 --- a/arch/powerpc/platforms/pseries/rtasd.c +++ b/arch/powerpc/platforms/pseries/rtasd.c @@ -363,7 +363,7 @@ static int get_eventscan_parms(void) node = of_find_node_by_path("/rtas"); - ip = get_property(node, "rtas-event-scan-rate", NULL); + ip = of_get_property(node, "rtas-event-scan-rate", NULL); if (ip == NULL) { printk(KERN_ERR "rtasd: no rtas-event-scan-rate\n"); of_node_put(node); diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 34aff47..33eec28 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -65,6 +65,7 @@ #include <asm/udbg.h> #include <asm/smp.h> #include <asm/firmware.h> +#include <asm/eeh.h> #include "plpar_wrappers.h" #include "pseries.h" @@ -92,7 +93,7 @@ static void pSeries_show_cpuinfo(struct seq_file *m) root = of_find_node_by_path("/"); if (root) - model = get_property(root, "model", NULL); + model = of_get_property(root, "model", NULL); seq_printf(m, "machine\t\t: CHRP %s\n", model); of_node_put(root); } @@ -138,8 +139,8 @@ static void __init pseries_mpic_init_IRQ(void) struct mpic *mpic; np = of_find_node_by_path("/"); - naddr = prom_n_addr_cells(np); - opprop = get_property(np, "platform-open-pic", &opplen); + naddr = of_n_addr_cells(np); + opprop = of_get_property(np, "platform-open-pic", &opplen); if (opprop != 0) { openpic_addr = of_read_number(opprop, naddr); printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr); @@ -188,11 +189,11 @@ static void __init pseries_mpic_init_IRQ(void) break; if (strcmp(np->name, "pci") != 0) continue; - addrp = get_property(np, "8259-interrupt-acknowledge", + addrp = of_get_property(np, "8259-interrupt-acknowledge", NULL); if (addrp == NULL) continue; - naddr = prom_n_addr_cells(np); + naddr = of_n_addr_cells(np); intack = addrp[naddr-1]; if (naddr > 1) intack |= ((unsigned long)addrp[naddr-2]) << 32; @@ -225,7 +226,7 @@ static void __init pseries_discover_pic(void) for (np = NULL; (np = of_find_node_by_name(np, "interrupt-controller"));) { - typep = get_property(np, "compatible", NULL); + typep = of_get_property(np, "compatible", NULL); if (strstr(typep, "open-pic")) { pSeries_mpic_node = of_node_get(np); ppc_md.init_IRQ = pseries_mpic_init_IRQ; @@ -334,32 +335,6 @@ static void __init pSeries_init_early(void) DBG(" <- pSeries_init_early()\n"); } - -static int pSeries_check_legacy_ioport(unsigned int baseport) -{ - struct device_node *np; - -#define I8042_DATA_REG 0x60 -#define FDC_BASE 0x3f0 - - - switch(baseport) { - case I8042_DATA_REG: - np = of_find_node_by_type(NULL, "8042"); - if (np == NULL) - return -ENODEV; - of_node_put(np); - break; - case FDC_BASE: - np = of_find_node_by_type(NULL, "fdc"); - if (np == NULL) - return -ENODEV; - of_node_put(np); - break; - } - return 0; -} - /* * Called very early, MMU is off, device-tree isn't unflattened */ @@ -514,6 +489,10 @@ void pSeries_power_off(void) for (;;); } +#ifndef CONFIG_PCI +void pSeries_final_fixup(void) { } +#endif + define_machine(pseries) { .name = "pSeries", .probe = pSeries_probe, @@ -532,7 +511,6 @@ define_machine(pseries) { .set_rtc_time = rtas_set_rtc_time, .calibrate_decr = generic_calibrate_decr, .progress = rtas_progress, - .check_legacy_ioport = pSeries_check_legacy_ioport, .system_reset_exception = pSeries_system_reset_exception, .machine_check_exception = pSeries_machine_check_exception, }; diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 81d172d..896cbf3 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -576,7 +576,7 @@ static void __init xics_init_one_node(struct device_node *np, * This happens to be the case so far but we are playing with fire... * should be fixed one of these days. -BenH. */ - ireg = get_property(np, "ibm,interrupt-server-ranges", NULL); + ireg = of_get_property(np, "ibm,interrupt-server-ranges", NULL); /* Do that ever happen ? we'll know soon enough... but even good'old * f80 does have that property .. @@ -588,7 +588,7 @@ static void __init xics_init_one_node(struct device_node *np, */ *indx = *ireg; } - ireg = get_property(np, "reg", &ilen); + ireg = of_get_property(np, "reg", &ilen); if (!ireg) panic("xics_init_IRQ: can't find interrupt reg property"); @@ -640,10 +640,10 @@ static void __init xics_setup_8259_cascade(void) break; if (strcmp(np->name, "pci") != 0) continue; - addrp = get_property(np, "8259-interrupt-acknowledge", NULL); + addrp = of_get_property(np, "8259-interrupt-acknowledge", NULL); if (addrp == NULL) continue; - naddr = prom_n_addr_cells(np); + naddr = of_n_addr_cells(np); intack = addrp[naddr-1]; if (naddr > 1) intack |= ((unsigned long)addrp[naddr-2]) << 32; @@ -664,10 +664,11 @@ static struct device_node *cpuid_to_of_node(int cpu) int i, len; const u32 *intserv; - intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len); + intserv = of_get_property(np, "ibm,ppc-interrupt-server#s", + &len); if (!intserv) - intserv = get_property(np, "reg", &len); + intserv = of_get_property(np, "reg", &len); i = len / sizeof(u32); @@ -709,7 +710,7 @@ void __init xics_init_IRQ(void) /* Find the server numbers for the boot cpu. */ np = cpuid_to_of_node(boot_cpuid); BUG_ON(!np); - ireg = get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen); + ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen); if (!ireg) goto skip_gserver_check; i = ilen / sizeof(int); @@ -725,7 +726,7 @@ void __init xics_init_IRQ(void) default_server = hcpuid; default_distrib_server = ireg[j+1]; - isize = get_property(np, + isize = of_get_property(np, "ibm,interrupt-server#-size", NULL); if (isize) interrupt_server_size = *isize; diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 26ca3ff..e96ca96 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile @@ -11,12 +11,17 @@ obj-$(CONFIG_PPC_PMI) += pmi.o obj-$(CONFIG_U3_DART) += dart_iommu.o obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o obj-$(CONFIG_FSL_SOC) += fsl_soc.o +obj-$(CONFIG_FSL_PCIE) += fsl_pcie.o obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o obj-$(CONFIG_QUICC_ENGINE) += qe_lib/ +# contains only the suspend handler for time +obj-$(CONFIG_PM) += timer.o + ifeq ($(CONFIG_PPC_MERGE),y) obj-$(CONFIG_PPC_I8259) += i8259.o obj-$(CONFIG_PPC_83xx) += ipic.o +obj-$(CONFIG_4xx) += uic.o endif # Temporary hack until we have migrated to asm-powerpc diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index 1488535..336186d 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c @@ -333,7 +333,7 @@ void iommu_init_early_dart(void) ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_dart; /* Setup pci_dma ops */ - pci_dma_ops = &dma_iommu_ops; + set_pci_dma_ops(&dma_iommu_ops); return; } @@ -343,7 +343,7 @@ void iommu_init_early_dart(void) ppc_md.pci_dma_bus_setup = NULL; /* Setup pci_dma ops */ - pci_dma_ops = &dma_direct_ops; + set_pci_dma_ops(&dma_direct_ops); } diff --git a/arch/powerpc/sysdev/dcr.c b/arch/powerpc/sysdev/dcr.c index 1fc5819..574b6ef 100644 --- a/arch/powerpc/sysdev/dcr.c +++ b/arch/powerpc/sysdev/dcr.c @@ -26,7 +26,7 @@ unsigned int dcr_resource_start(struct device_node *np, unsigned int index) { unsigned int ds; - const u32 *dr = get_property(np, "dcr-reg", &ds); + const u32 *dr = of_get_property(np, "dcr-reg", &ds); if (dr == NULL || ds & 1 || index >= (ds / 8)) return 0; @@ -37,7 +37,7 @@ unsigned int dcr_resource_start(struct device_node *np, unsigned int index) unsigned int dcr_resource_len(struct device_node *np, unsigned int index) { unsigned int ds; - const u32 *dr = get_property(np, "dcr-reg", &ds); + const u32 *dr = of_get_property(np, "dcr-reg", &ds); if (dr == NULL || ds & 1 || index >= (ds / 8)) return 0; @@ -53,9 +53,9 @@ static struct device_node * find_dcr_parent(struct device_node * node) const u32 *p; for (par = of_node_get(node); par;) { - if (get_property(par, "dcr-controller", NULL)) + if (of_get_property(par, "dcr-controller", NULL)) break; - p = get_property(par, "dcr-parent", NULL); + p = of_get_property(par, "dcr-parent", NULL); tmp = par; if (p == NULL) par = of_get_parent(par); @@ -80,13 +80,13 @@ u64 of_translate_dcr_address(struct device_node *dev, return OF_BAD_ADDR; /* Stride is not properly defined yet, default to 0x10 for Axon */ - p = get_property(dp, "dcr-mmio-stride", NULL); + p = of_get_property(dp, "dcr-mmio-stride", NULL); stride = (p == NULL) ? 0x10 : *p; /* XXX FIXME: Which property name is to use of the 2 following ? */ - p = get_property(dp, "dcr-mmio-range", NULL); + p = of_get_property(dp, "dcr-mmio-range", NULL); if (p == NULL) - p = get_property(dp, "dcr-mmio-space", NULL); + p = of_get_property(dp, "dcr-mmio-space", NULL); if (p == NULL) return OF_BAD_ADDR; diff --git a/arch/powerpc/platforms/86xx/mpc86xx_pcie.c b/arch/powerpc/sysdev/fsl_pcie.c index a2f4f73..041c07e 100644 --- a/arch/powerpc/platforms/86xx/mpc86xx_pcie.c +++ b/arch/powerpc/sysdev/fsl_pcie.c @@ -24,8 +24,6 @@ #include <asm/pci-bridge.h> #include <asm/machdep.h> -#include "mpc86xx.h" - #define PCI_CFG_OUT out_be32 /* ERRATA PCI-Ex 14 PCIE Controller timeout */ diff --git a/arch/powerpc/sysdev/fsl_pcie.h b/arch/powerpc/sysdev/fsl_pcie.h new file mode 100644 index 0000000..8d9779c --- /dev/null +++ b/arch/powerpc/sysdev/fsl_pcie.h @@ -0,0 +1,94 @@ +/* + * MPC85xx/86xx PCI Express structure define + * + * 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. + * + */ + +#ifdef __KERNEL__ +#ifndef __POWERPC_FSL_PCIE_H +#define __POWERPC_FSL_PCIE_H + +/* PCIE Express IO block registers in 85xx/86xx */ + +struct ccsr_pex { + __be32 __iomem pex_config_addr; /* 0x.000 - PCI Express Configuration Address Register */ + __be32 __iomem pex_config_data; /* 0x.004 - PCI Express Configuration Data Register */ + u8 __iomem res1[4]; + __be32 __iomem pex_otb_cpl_tor; /* 0x.00c - PCI Express Outbound completion timeout register */ + __be32 __iomem pex_conf_tor; /* 0x.010 - PCI Express configuration timeout register */ + u8 __iomem res2[12]; + __be32 __iomem pex_pme_mes_dr; /* 0x.020 - PCI Express PME and message detect register */ + __be32 __iomem pex_pme_mes_disr; /* 0x.024 - PCI Express PME and message disable register */ + __be32 __iomem pex_pme_mes_ier; /* 0x.028 - PCI Express PME and message interrupt enable register */ + __be32 __iomem pex_pmcr; /* 0x.02c - PCI Express power management command register */ + u8 __iomem res3[3024]; + __be32 __iomem pexotar0; /* 0x.c00 - PCI Express outbound translation address register 0 */ + __be32 __iomem pexotear0; /* 0x.c04 - PCI Express outbound translation extended address register 0*/ + u8 __iomem res4[8]; + __be32 __iomem pexowar0; /* 0x.c10 - PCI Express outbound window attributes register 0*/ + u8 __iomem res5[12]; + __be32 __iomem pexotar1; /* 0x.c20 - PCI Express outbound translation address register 1 */ + __be32 __iomem pexotear1; /* 0x.c24 - PCI Express outbound translation extended address register 1*/ + __be32 __iomem pexowbar1; /* 0x.c28 - PCI Express outbound window base address register 1*/ + u8 __iomem res6[4]; + __be32 __iomem pexowar1; /* 0x.c30 - PCI Express outbound window attributes register 1*/ + u8 __iomem res7[12]; + __be32 __iomem pexotar2; /* 0x.c40 - PCI Express outbound translation address register 2 */ + __be32 __iomem pexotear2; /* 0x.c44 - PCI Express outbound translation extended address register 2*/ + __be32 __iomem pexowbar2; /* 0x.c48 - PCI Express outbound window base address register 2*/ + u8 __iomem res8[4]; + __be32 __iomem pexowar2; /* 0x.c50 - PCI Express outbound window attributes register 2*/ + u8 __iomem res9[12]; + __be32 __iomem pexotar3; /* 0x.c60 - PCI Express outbound translation address register 3 */ + __be32 __iomem pexotear3; /* 0x.c64 - PCI Express outbound translation extended address register 3*/ + __be32 __iomem pexowbar3; /* 0x.c68 - PCI Express outbound window base address register 3*/ + u8 __iomem res10[4]; + __be32 __iomem pexowar3; /* 0x.c70 - PCI Express outbound window attributes register 3*/ + u8 __iomem res11[12]; + __be32 __iomem pexotar4; /* 0x.c80 - PCI Express outbound translation address register 4 */ + __be32 __iomem pexotear4; /* 0x.c84 - PCI Express outbound translation extended address register 4*/ + __be32 __iomem pexowbar4; /* 0x.c88 - PCI Express outbound window base address register 4*/ + u8 __iomem res12[4]; + __be32 __iomem pexowar4; /* 0x.c90 - PCI Express outbound window attributes register 4*/ + u8 __iomem res13[12]; + u8 __iomem res14[256]; + __be32 __iomem pexitar3; /* 0x.da0 - PCI Express inbound translation address register 3 */ + u8 __iomem res15[4]; + __be32 __iomem pexiwbar3; /* 0x.da8 - PCI Express inbound window base address register 3 */ + __be32 __iomem pexiwbear3; /* 0x.dac - PCI Express inbound window base extended address register 3 */ + __be32 __iomem pexiwar3; /* 0x.db0 - PCI Express inbound window attributes register 3 */ + u8 __iomem res16[12]; + __be32 __iomem pexitar2; /* 0x.dc0 - PCI Express inbound translation address register 2 */ + u8 __iomem res17[4]; + __be32 __iomem pexiwbar2; /* 0x.dc8 - PCI Express inbound window base address register 2 */ + __be32 __iomem pexiwbear2; /* 0x.dcc - PCI Express inbound window base extended address register 2 */ + __be32 __iomem pexiwar2; /* 0x.dd0 - PCI Express inbound window attributes register 2 */ + u8 __iomem res18[12]; + __be32 __iomem pexitar1; /* 0x.de0 - PCI Express inbound translation address register 2 */ + u8 __iomem res19[4]; + __be32 __iomem pexiwbar1; /* 0x.de8 - PCI Express inbound window base address register 2 */ + __be32 __iomem pexiwbear1; /* 0x.dec - PCI Express inbound window base extended address register 2 */ + __be32 __iomem pexiwar1; /* 0x.df0 - PCI Express inbound window attributes register 2 */ + u8 __iomem res20[12]; + __be32 __iomem pex_err_dr; /* 0x.e00 - PCI Express error detect register */ + u8 __iomem res21[4]; + __be32 __iomem pex_err_en; /* 0x.e08 - PCI Express error interrupt enable register */ + u8 __iomem res22[4]; + __be32 __iomem pex_err_disr; /* 0x.e10 - PCI Express error disable register */ + u8 __iomem res23[12]; + __be32 __iomem pex_err_cap_stat; /* 0x.e20 - PCI Express error capture status register */ + u8 __iomem res24[4]; + __be32 __iomem pex_err_cap_r0; /* 0x.e28 - PCI Express error capture register 0 */ + __be32 __iomem pex_err_cap_r1; /* 0x.e2c - PCI Express error capture register 0 */ + __be32 __iomem pex_err_cap_r2; /* 0x.e30 - PCI Express error capture register 0 */ + __be32 __iomem pex_err_cap_r3; /* 0x.e34 - PCI Express error capture register 0 */ +}; + +#endif /* __POWERPC_FSL_PCIE_H */ +#endif /* __KERNEL__ */ diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index d20f0292..8a123c7 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c @@ -52,7 +52,7 @@ phys_addr_t get_immrbase(void) soc = of_find_node_by_type(NULL, "soc"); if (soc) { unsigned int size; - const void *prop = get_property(soc, "reg", &size); + const void *prop = of_get_property(soc, "reg", &size); if (prop) immrbase = of_translate_address(soc, prop); @@ -78,8 +78,8 @@ u32 get_brgfreq(void) node = of_find_node_by_type(NULL, "cpm"); if (node) { unsigned int size; - const unsigned int *prop = get_property(node, "brg-frequency", - &size); + const unsigned int *prop = of_get_property(node, + "brg-frequency", &size); if (prop) brgfreq = *prop; @@ -103,8 +103,8 @@ u32 get_baudrate(void) node = of_find_node_by_type(NULL, "serial"); if (node) { unsigned int size; - const unsigned int *prop = get_property(node, "current-speed", - &size); + const unsigned int *prop = of_get_property(node, + "current-speed", &size); if (prop) fs_baudrate = *prop; @@ -153,7 +153,8 @@ static int __init gfar_mdio_of_init(void) while ((child = of_get_next_child(np, child)) != NULL) { int irq = irq_of_parse_and_map(child, 0); if (irq != NO_IRQ) { - const u32 *id = get_property(child, "reg", NULL); + const u32 *id = of_get_property(child, + "reg", NULL); mdio_data.irq[*id] = irq; } } @@ -209,7 +210,7 @@ static int __init gfar_of_init(void) of_irq_to_resource(np, 0, &r[1]); - model = get_property(np, "model", NULL); + model = of_get_property(np, "model", NULL); /* If we aren't the FEC we have multiple interrupts */ if (model && strcasecmp(model, "FEC")) { @@ -253,7 +254,7 @@ static int __init gfar_of_init(void) FSL_GIANFAR_DEV_HAS_VLAN | FSL_GIANFAR_DEV_HAS_EXTENDED_HASH; - ph = get_property(np, "phy-handle", NULL); + ph = of_get_property(np, "phy-handle", NULL); phy = of_find_node_by_phandle(*ph); if (phy == NULL) { @@ -263,7 +264,7 @@ static int __init gfar_of_init(void) mdio = of_get_parent(phy); - id = get_property(phy, "reg", NULL); + id = of_get_property(phy, "reg", NULL); ret = of_address_to_resource(mdio, 0, &res); if (ret) { of_node_put(phy); @@ -325,11 +326,11 @@ static int __init fsl_i2c_of_init(void) } i2c_data.device_flags = 0; - flags = get_property(np, "dfsrr", NULL); + flags = of_get_property(np, "dfsrr", NULL); if (flags) i2c_data.device_flags |= FSL_I2C_DEV_SEPARATE_DFSRR; - flags = get_property(np, "fsl5200-clocking", NULL); + flags = of_get_property(np, "fsl5200-clocking", NULL); if (flags) i2c_data.device_flags |= FSL_I2C_DEV_CLOCK_5200; @@ -374,7 +375,7 @@ static int __init mpc83xx_wdt_init(void) goto nosoc; } - freq = get_property(soc, "bus-frequency", NULL); + freq = of_get_property(soc, "bus-frequency", NULL); if (!freq) { ret = -ENODEV; goto err; @@ -466,15 +467,15 @@ static int __init fsl_usb_of_init(void) usb_data.operating_mode = FSL_USB2_MPH_HOST; - prop = get_property(np, "port0", NULL); + prop = of_get_property(np, "port0", NULL); if (prop) usb_data.port_enables |= FSL_USB2_PORT0_ENABLED; - prop = get_property(np, "port1", NULL); + prop = of_get_property(np, "port1", NULL); if (prop) usb_data.port_enables |= FSL_USB2_PORT1_ENABLED; - prop = get_property(np, "phy_type", NULL); + prop = of_get_property(np, "phy_type", NULL); usb_data.phy_mode = determine_usb_phy(prop); ret = @@ -501,7 +502,7 @@ static int __init fsl_usb_of_init(void) of_irq_to_resource(np, 0, &r[1]); - prop = get_property(np, "dr_mode", NULL); + prop = of_get_property(np, "dr_mode", NULL); if (!prop || !strcmp(prop, "host")) { usb_data.operating_mode = FSL_USB2_DR_HOST; @@ -538,7 +539,7 @@ static int __init fsl_usb_of_init(void) goto err; } - prop = get_property(np, "phy_type", NULL); + prop = of_get_property(np, "phy_type", NULL); usb_data.phy_mode = determine_usb_phy(prop); if (usb_dev_dr_host) { @@ -633,7 +634,7 @@ static int __init fs_enet_of_init(void) goto err; } - model = get_property(np, "model", NULL); + model = of_get_property(np, "model", NULL); if (model == NULL) { ret = -ENODEV; goto unreg; @@ -643,7 +644,7 @@ static int __init fs_enet_of_init(void) if (mac_addr) memcpy(fs_enet_data.macaddr, mac_addr, 6); - ph = get_property(np, "phy-handle", NULL); + ph = of_get_property(np, "phy-handle", NULL); phy = of_find_node_by_phandle(*ph); if (phy == NULL) { @@ -651,12 +652,12 @@ static int __init fs_enet_of_init(void) goto unreg; } - phy_addr = get_property(phy, "reg", NULL); + phy_addr = of_get_property(phy, "reg", NULL); fs_enet_data.phy_addr = *phy_addr; - phy_irq = get_property(phy, "interrupts", NULL); + phy_irq = of_get_property(phy, "interrupts", NULL); - id = get_property(np, "device-id", NULL); + id = of_get_property(np, "device-id", NULL); fs_enet_data.fs_no = *id; strcpy(fs_enet_data.fs_type, model); @@ -668,8 +669,10 @@ static int __init fs_enet_of_init(void) goto unreg; } - fs_enet_data.clk_rx = *((u32 *) get_property(np, "rx-clock", NULL)); - fs_enet_data.clk_tx = *((u32 *) get_property(np, "tx-clock", NULL)); + fs_enet_data.clk_rx = *((u32 *)of_get_property(np, + "rx-clock", NULL)); + fs_enet_data.clk_tx = *((u32 *)of_get_property(np, + "tx-clock", NULL)); if (strstr(model, "FCC")) { int fcc_index = *id - 1; @@ -690,7 +693,7 @@ static int __init fs_enet_of_init(void) fs_enet_data.bus_id = (char*)&bus_id[(*id)]; fs_enet_data.init_ioports = init_fcc_ioports; - mdio_bb_prop = get_property(phy, "bitbang", NULL); + mdio_bb_prop = of_get_property(phy, "bitbang", NULL); if (mdio_bb_prop) { struct platform_device *fs_enet_mdio_bb_dev; struct fs_mii_bb_platform_info fs_enet_mdio_bb_data; @@ -796,10 +799,10 @@ static int __init cpm_uart_of_init(void) goto err; } - id = get_property(np, "device-id", NULL); + id = of_get_property(np, "device-id", NULL); cpm_uart_data.fs_no = *id; - model = (char*)get_property(np, "model", NULL); + model = of_get_property(np, "model", NULL); strcpy(cpm_uart_data.fs_type, model); cpm_uart_data.uart_clk = ppc_proc_freq; @@ -808,8 +811,10 @@ static int __init cpm_uart_of_init(void) cpm_uart_data.tx_buf_size = 32; cpm_uart_data.rx_num_fifo = 4; cpm_uart_data.rx_buf_size = 32; - cpm_uart_data.clk_rx = *((u32 *) get_property(np, "rx-clock", NULL)); - cpm_uart_data.clk_tx = *((u32 *) get_property(np, "tx-clock", NULL)); + cpm_uart_data.clk_rx = *((u32 *)of_get_property(np, + "rx-clock", NULL)); + cpm_uart_data.clk_tx = *((u32 *)of_get_property(np, + "tx-clock", NULL)); ret = platform_device_add_data(cpm_uart_dev, &cpm_uart_data, @@ -833,7 +838,7 @@ arch_initcall(cpm_uart_of_init); #ifdef CONFIG_8xx extern void init_scc_ioports(struct fs_platform_info*); -extern int platform_device_skip(char *model, int id); +extern int platform_device_skip(const char *model, int id); static int __init fs_enet_mdio_of_init(void) { @@ -900,21 +905,22 @@ static int __init fs_enet_of_init(void) struct resource r[4]; struct device_node *phy = NULL, *mdio = NULL; struct fs_platform_info fs_enet_data; - unsigned int *id, *phy_addr; + const unsigned int *id; + const unsigned int *phy_addr; void *mac_addr; - phandle *ph; - char *model; + const phandle *ph; + const char *model; memset(r, 0, sizeof(r)); memset(&fs_enet_data, 0, sizeof(fs_enet_data)); - model = (char *)get_property(np, "model", NULL); + model = of_get_property(np, "model", NULL); if (model == NULL) { ret = -ENODEV; goto unreg; } - id = (u32 *) get_property(np, "device-id", NULL); + id = of_get_property(np, "device-id", NULL); fs_enet_data.fs_no = *id; if (platform_device_skip(model, *id)) @@ -929,12 +935,12 @@ static int __init fs_enet_of_init(void) if (mac_addr) memcpy(fs_enet_data.macaddr, mac_addr, 6); - ph = (phandle *) get_property(np, "phy-handle", NULL); + ph = of_get_property(np, "phy-handle", NULL); if (ph != NULL) phy = of_find_node_by_phandle(*ph); if (phy != NULL) { - phy_addr = (u32 *) get_property(phy, "reg", NULL); + phy_addr = of_get_property(phy, "reg", NULL); fs_enet_data.phy_addr = *phy_addr; fs_enet_data.has_phy = 1; @@ -947,7 +953,7 @@ static int __init fs_enet_of_init(void) } } - model = (char*)get_property(np, "model", NULL); + model = of_get_property(np, "model", NULL); strcpy(fs_enet_data.fs_type, model); if (strstr(model, "FEC")) { @@ -1038,8 +1044,8 @@ static int __init cpm_smc_uart_of_init(void) i++) { struct resource r[3]; struct fs_uart_platform_info cpm_uart_data; - int *id; - char *model; + const int *id; + const char *model; memset(r, 0, sizeof(r)); memset(&cpm_uart_data, 0, sizeof(cpm_uart_data)); @@ -1066,10 +1072,10 @@ static int __init cpm_smc_uart_of_init(void) goto err; } - model = (char*)get_property(np, "model", NULL); + model = of_get_property(np, "model", NULL); strcpy(cpm_uart_data.fs_type, model); - id = (int*)get_property(np, "device-id", NULL); + id = of_get_property(np, "device-id", NULL); cpm_uart_data.fs_no = *id; cpm_uart_data.uart_clk = ppc_proc_freq; diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index bcfb900..0b84b7c 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -304,7 +304,7 @@ static void __init mpic_test_broken_ipi(struct mpic *mpic) } } -#ifdef CONFIG_MPIC_BROKEN_U3 +#ifdef CONFIG_MPIC_U3_HT_IRQS /* Test if an interrupt is sourced from HyperTransport (used on broken U3s) * to force the edge setting on the MPIC and do the ack workaround. @@ -476,7 +476,7 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic) } } -#else /* CONFIG_MPIC_BROKEN_U3 */ +#else /* CONFIG_MPIC_U3_HT_IRQS */ static inline int mpic_is_ht_interrupt(struct mpic *mpic, unsigned int source) { @@ -487,7 +487,7 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic) { } -#endif /* CONFIG_MPIC_BROKEN_U3 */ +#endif /* CONFIG_MPIC_U3_HT_IRQS */ #define mpic_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq) @@ -615,7 +615,7 @@ static void mpic_end_irq(unsigned int irq) mpic_eoi(mpic); } -#ifdef CONFIG_MPIC_BROKEN_U3 +#ifdef CONFIG_MPIC_U3_HT_IRQS static void mpic_unmask_ht_irq(unsigned int irq) { @@ -665,7 +665,7 @@ static void mpic_end_ht_irq(unsigned int irq) mpic_ht_end_irq(mpic, src); mpic_eoi(mpic); } -#endif /* !CONFIG_MPIC_BROKEN_U3 */ +#endif /* !CONFIG_MPIC_U3_HT_IRQS */ #ifdef CONFIG_SMP @@ -788,7 +788,7 @@ static struct irq_chip mpic_ipi_chip = { }; #endif /* CONFIG_SMP */ -#ifdef CONFIG_MPIC_BROKEN_U3 +#ifdef CONFIG_MPIC_U3_HT_IRQS static struct irq_chip mpic_irq_ht_chip = { .startup = mpic_startup_ht_irq, .shutdown = mpic_shutdown_ht_irq, @@ -797,7 +797,7 @@ static struct irq_chip mpic_irq_ht_chip = { .eoi = mpic_end_ht_irq, .set_type = mpic_set_irq_type, }; -#endif /* CONFIG_MPIC_BROKEN_U3 */ +#endif /* CONFIG_MPIC_U3_HT_IRQS */ static int mpic_host_match(struct irq_host *h, struct device_node *node) @@ -837,11 +837,11 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq, /* Default chip */ chip = &mpic->hc_irq; -#ifdef CONFIG_MPIC_BROKEN_U3 +#ifdef CONFIG_MPIC_U3_HT_IRQS /* Check for HT interrupts, override vecpri */ if (mpic_is_ht_interrupt(mpic, hw)) chip = &mpic->hc_ht_irq; -#endif /* CONFIG_MPIC_BROKEN_U3 */ +#endif /* CONFIG_MPIC_U3_HT_IRQS */ DBG("mpic: mapping to irq chip @%p\n", chip); @@ -937,12 +937,12 @@ struct mpic * __init mpic_alloc(struct device_node *node, mpic->hc_irq.typename = name; if (flags & MPIC_PRIMARY) mpic->hc_irq.set_affinity = mpic_set_affinity; -#ifdef CONFIG_MPIC_BROKEN_U3 +#ifdef CONFIG_MPIC_U3_HT_IRQS mpic->hc_ht_irq = mpic_irq_ht_chip; mpic->hc_ht_irq.typename = name; if (flags & MPIC_PRIMARY) mpic->hc_ht_irq.set_affinity = mpic_set_affinity; -#endif /* CONFIG_MPIC_BROKEN_U3 */ +#endif /* CONFIG_MPIC_U3_HT_IRQS */ #ifdef CONFIG_SMP mpic->hc_ipi = mpic_ipi_chip; @@ -970,7 +970,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, mpic->spurious_vec = intvec_top; /* Check for "big-endian" in device-tree */ - if (node && get_property(node, "big-endian", NULL) != NULL) + if (node && of_get_property(node, "big-endian", NULL) != NULL) mpic->flags |= MPIC_BIG_ENDIAN; @@ -986,13 +986,13 @@ struct mpic * __init mpic_alloc(struct device_node *node, BUG_ON(paddr == 0 && node == NULL); /* If no physical address passed in, check if it's dcr based */ - if (paddr == 0 && get_property(node, "dcr-reg", NULL) != NULL) + if (paddr == 0 && of_get_property(node, "dcr-reg", NULL) != NULL) mpic->flags |= MPIC_USES_DCR; #ifdef CONFIG_PPC_DCR if (mpic->flags & MPIC_USES_DCR) { const u32 *dbasep; - dbasep = get_property(node, "dcr-reg", NULL); + dbasep = of_get_property(node, "dcr-reg", NULL); BUG_ON(dbasep == NULL); mpic->dcr_base = *dbasep; mpic->reg_type = mpic_access_dcr; @@ -1006,7 +1006,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, */ if (paddr == 0 && !(mpic->flags & MPIC_USES_DCR)) { const u32 *reg; - reg = get_property(node, "reg", NULL); + reg = of_get_property(node, "reg", NULL); BUG_ON(reg == NULL); paddr = of_translate_address(node, reg); BUG_ON(paddr == OF_BAD_ADDR); @@ -1142,7 +1142,7 @@ void __init mpic_init(struct mpic *mpic) /* Do the HT PIC fixups on U3 broken mpic */ DBG("MPIC flags: %x\n", mpic->flags); - if ((mpic->flags & MPIC_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY)) + if ((mpic->flags & MPIC_U3_HT_IRQS) && (mpic->flags & MPIC_PRIMARY)) mpic_scan_ht_pics(mpic); for (i = 0; i < mpic->num_sources; i++) { diff --git a/arch/powerpc/sysdev/pmi.c b/arch/powerpc/sysdev/pmi.c index a528201..85a7c99 100644 --- a/arch/powerpc/sysdev/pmi.c +++ b/arch/powerpc/sysdev/pmi.c @@ -33,7 +33,7 @@ #include <asm/of_platform.h> #include <asm/io.h> #include <asm/pmi.h> - +#include <asm/prom.h> struct pmi_data { struct list_head handler; @@ -49,21 +49,6 @@ struct pmi_data { }; - -static void __iomem *of_iomap(struct device_node *np) -{ - struct resource res; - - if (of_address_to_resource(np, 0, &res)) - return NULL; - - pr_debug("Resource start: 0x%lx\n", res.start); - pr_debug("Resource end: 0x%lx\n", res.end); - - return ioremap(res.start, 1 + res.end - res.start); -} - - static int pmi_irq_handler(int irq, void *dev_id) { struct pmi_data *data; @@ -118,6 +103,7 @@ out: static struct of_device_id pmi_match[] = { { .type = "ibm,pmi", .name = "ibm,pmi" }, + { .type = "ibm,pmi" }, {}, }; @@ -153,7 +139,7 @@ static int pmi_of_probe(struct of_device *dev, goto out; } - data->pmi_reg = of_iomap(np); + data->pmi_reg = of_iomap(np, 0); if (!data->pmi_reg) { printk(KERN_ERR "pmi: invalid register address.\n"); rc = -EFAULT; @@ -279,6 +265,9 @@ void pmi_register_handler(struct of_device *device, struct pmi_data *data; data = device->dev.driver_data; + if (!data) + return; + spin_lock(&data->handler_spinlock); list_add_tail(&handler->node, &data->handler); spin_unlock(&data->handler_spinlock); @@ -289,10 +278,12 @@ void pmi_unregister_handler(struct of_device *device, struct pmi_handler *handler) { struct pmi_data *data; + data = device->dev.driver_data; - pr_debug("pmi: unregistering handler %p\n", handler); + if (!data) + return; - data = device->dev.driver_data; + pr_debug("pmi: unregistering handler %p\n", handler); spin_lock(&data->handler_spinlock); list_del(&handler->node); diff --git a/arch/powerpc/sysdev/qe_lib/Kconfig b/arch/powerpc/sysdev/qe_lib/Kconfig index a725e80..887739f 100644 --- a/arch/powerpc/sysdev/qe_lib/Kconfig +++ b/arch/powerpc/sysdev/qe_lib/Kconfig @@ -2,11 +2,8 @@ # QE Communication options # -menu "QE Options" - depends on QUICC_ENGINE - config UCC_SLOW - bool "UCC Slow Protocols Support" + bool default n select UCC help @@ -14,10 +11,9 @@ config UCC_SLOW protocols: UART, BISYNC, QMC config UCC_FAST - bool "UCC Fast Protocols Support" + bool default n select UCC - select UCC_SLOW help This option provides qe_lib support to UCC fast protocols: HDLC, Ethernet, ATM, transparent @@ -26,5 +22,3 @@ config UCC bool default y if UCC_FAST || UCC_SLOW -endmenu - diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c index 43f6cc9..7f4c075 100644 --- a/arch/powerpc/sysdev/qe_lib/qe.c +++ b/arch/powerpc/sysdev/qe_lib/qe.c @@ -71,7 +71,7 @@ phys_addr_t get_qe_base(void) qe = of_find_node_by_type(NULL, "qe"); if (qe) { unsigned int size; - const void *prop = get_property(qe, "reg", &size); + const void *prop = of_get_property(qe, "reg", &size); qebase = of_translate_address(qe, prop); of_node_put(qe); }; @@ -158,7 +158,7 @@ unsigned int get_brg_clk(void) qe = of_find_node_by_type(NULL, "qe"); if (qe) { unsigned int size; - const u32 *prop = get_property(qe, "brg-frequency", &size); + const u32 *prop = of_get_property(qe, "brg-frequency", &size); brg_clk = *prop; of_node_put(qe); }; diff --git a/arch/powerpc/sysdev/qe_lib/qe_io.c b/arch/powerpc/sysdev/qe_lib/qe_io.c index 0afe6bf..e32b45b 100644 --- a/arch/powerpc/sysdev/qe_lib/qe_io.c +++ b/arch/powerpc/sysdev/qe_lib/qe_io.c @@ -53,7 +53,7 @@ int par_io_init(struct device_node *np) return ret; par_io = ioremap(res.start, res.end - res.start + 1); - num_ports = get_property(np, "num-ports", NULL); + num_ports = of_get_property(np, "num-ports", NULL); if (num_ports) num_par_io_ports = *num_ports; @@ -161,7 +161,7 @@ int par_io_of_config(struct device_node *np) return -1; } - ph = get_property(np, "pio-handle", NULL); + ph = of_get_property(np, "pio-handle", NULL); if (ph == 0) { printk(KERN_ERR "pio-handle not available \n"); return -1; @@ -169,7 +169,7 @@ int par_io_of_config(struct device_node *np) pio = of_find_node_by_phandle(*ph); - pio_map = get_property(pio, "pio-map", &pio_map_len); + pio_map = of_get_property(pio, "pio-map", &pio_map_len); if (pio_map == NULL) { printk(KERN_ERR "pio-map is not set! \n"); return -1; diff --git a/arch/powerpc/sysdev/qe_lib/ucc_slow.c b/arch/powerpc/sysdev/qe_lib/ucc_slow.c index 817df73..b930d68 100644 --- a/arch/powerpc/sysdev/qe_lib/ucc_slow.c +++ b/arch/powerpc/sysdev/qe_lib/ucc_slow.c @@ -187,7 +187,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc uccs->us_pram = qe_muram_addr(uccs->us_pram_offset); /* Init Guemr register */ - if ((ret = ucc_init_guemr((struct ucc_common *) (us_info->regs)))) { + if ((ret = ucc_init_guemr((struct ucc_common *) us_regs))) { printk(KERN_ERR "%s: cannot init GUEMR", __FUNCTION__); ucc_slow_free(uccs); return ret; @@ -195,7 +195,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc /* Set UCC to slow type */ if ((ret = ucc_set_type(us_info->ucc_num, - (struct ucc_common *) (us_info->regs), + (struct ucc_common *) us_regs, UCC_SPEED_TYPE_SLOW))) { printk(KERN_ERR "%s: cannot set UCC type", __FUNCTION__); ucc_slow_free(uccs); diff --git a/arch/powerpc/sysdev/timer.c b/arch/powerpc/sysdev/timer.c new file mode 100644 index 0000000..4a01748 --- /dev/null +++ b/arch/powerpc/sysdev/timer.c @@ -0,0 +1,71 @@ +/* + * Common code to keep time when machine suspends. + * + * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> + * + * GPLv2 + */ + +#include <linux/time.h> +#include <linux/sysdev.h> +#include <asm/rtc.h> + +static unsigned long suspend_rtc_time; + +/* + * Reset the time after a sleep. + */ +static int timer_resume(struct sys_device *dev) +{ + struct timeval tv; + struct timespec ts; + struct rtc_time cur_rtc_tm; + unsigned long cur_rtc_time, diff; + + /* get current RTC time and convert to seconds */ + get_rtc_time(&cur_rtc_tm); + rtc_tm_to_time(&cur_rtc_tm, &cur_rtc_time); + + diff = cur_rtc_time - suspend_rtc_time; + + /* adjust time of day by seconds that elapsed while + * we were suspended */ + do_gettimeofday(&tv); + ts.tv_sec = tv.tv_sec + diff; + ts.tv_nsec = tv.tv_usec * NSEC_PER_USEC; + do_settimeofday(&ts); + + return 0; +} + +static int timer_suspend(struct sys_device *dev, pm_message_t state) +{ + struct rtc_time suspend_rtc_tm; + WARN_ON(!ppc_md.get_rtc_time); + + get_rtc_time(&suspend_rtc_tm); + rtc_tm_to_time(&suspend_rtc_tm, &suspend_rtc_time); + + return 0; +} + +static struct sysdev_class timer_sysclass = { + .resume = timer_resume, + .suspend = timer_suspend, + set_kset_name("timer"), +}; + +static struct sys_device device_timer = { + .id = 0, + .cls = &timer_sysclass, +}; + +static int time_init_device(void) +{ + int error = sysdev_class_register(&timer_sysclass); + if (!error) + error = sysdev_register(&device_timer); + return error; +} + +device_initcall(time_init_device); diff --git a/arch/powerpc/sysdev/tsi108_dev.c b/arch/powerpc/sysdev/tsi108_dev.c index 97f37ef..337039e 100644 --- a/arch/powerpc/sysdev/tsi108_dev.c +++ b/arch/powerpc/sysdev/tsi108_dev.c @@ -48,7 +48,7 @@ phys_addr_t get_csrbase(void) tsi = of_find_node_by_type(NULL, "tsi-bridge"); if (tsi) { unsigned int size; - const void *prop = get_property(tsi, "reg", &size); + const void *prop = of_get_property(tsi, "reg", &size); tsi108_csr_base = of_translate_address(tsi, prop); of_node_put(tsi); }; @@ -77,10 +77,10 @@ static int __init tsi108_eth_of_init(void) struct resource r[2]; struct device_node *phy; hw_info tsi_eth_data; - unsigned int *id; - unsigned int *phy_id; + const unsigned int *id; + const unsigned int *phy_id; const void *mac_addr; - phandle *ph; + const phandle *ph; memset(r, 0, sizeof(r)); memset(&tsi_eth_data, 0, sizeof(tsi_eth_data)); @@ -107,10 +107,10 @@ static int __init tsi108_eth_of_init(void) goto err; } - mac_addr = get_property(np, "address", NULL); + mac_addr = of_get_property(np, "address", NULL); memcpy(tsi_eth_data.mac_addr, mac_addr, 6); - ph = (phandle *) get_property(np, "phy-handle", NULL); + ph = of_get_property(np, "phy-handle", NULL); phy = of_find_node_by_phandle(*ph); if (phy == NULL) { @@ -118,8 +118,8 @@ static int __init tsi108_eth_of_init(void) goto unreg; } - id = (u32 *) get_property(phy, "reg", NULL); - phy_id = (u32 *) get_property(phy, "phy-id", NULL); + id = of_get_property(phy, "reg", NULL); + phy_id = of_get_property(phy, "phy-id", NULL); ret = of_address_to_resource(phy, 0, &res); if (ret) { of_node_put(phy); diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c index ae249c6..58b9e7f 100644 --- a/arch/powerpc/sysdev/tsi108_pci.c +++ b/arch/powerpc/sysdev/tsi108_pci.c @@ -211,7 +211,7 @@ int __init tsi108_setup_pci(struct device_node *dev) has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); /* Get bus range if any */ - 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)) { printk(KERN_WARNING "Can't get bus-range for %s, assume" " bus 0\n", dev->full_name); diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c new file mode 100644 index 0000000..968fb40 --- /dev/null +++ b/arch/powerpc/sysdev/uic.c @@ -0,0 +1,342 @@ +/* + * arch/powerpc/sysdev/uic.c + * + * IBM PowerPC 4xx Universal Interrupt Controller + * + * Copyright 2007 David Gibson <dwg@au1.ibm.com>, 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. + */ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/reboot.h> +#include <linux/slab.h> +#include <linux/stddef.h> +#include <linux/sched.h> +#include <linux/signal.h> +#include <linux/sysdev.h> +#include <linux/device.h> +#include <linux/bootmem.h> +#include <linux/spinlock.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <asm/irq.h> +#include <asm/io.h> +#include <asm/prom.h> +#include <asm/dcr.h> + +#define NR_UIC_INTS 32 + +#define UIC_SR 0x0 +#define UIC_ER 0x2 +#define UIC_CR 0x3 +#define UIC_PR 0x4 +#define UIC_TR 0x5 +#define UIC_MSR 0x6 +#define UIC_VR 0x7 +#define UIC_VCR 0x8 + +#define uic_irq_to_hw(virq) (irq_map[virq].hwirq) + +struct uic *primary_uic; + +struct uic { + int index; + int dcrbase; + + spinlock_t lock; + + /* The remapper for this UIC */ + struct irq_host *irqhost; + + /* For secondary UICs, the cascade interrupt's irqaction */ + struct irqaction cascade; + + /* The device node of the interrupt controller */ + struct device_node *of_node; +}; + +static void uic_unmask_irq(unsigned int virq) +{ + struct uic *uic = get_irq_chip_data(virq); + unsigned int src = uic_irq_to_hw(virq); + unsigned long flags; + u32 er; + + spin_lock_irqsave(&uic->lock, flags); + er = mfdcr(uic->dcrbase + UIC_ER); + er |= 1 << (31 - src); + mtdcr(uic->dcrbase + UIC_ER, er); + spin_unlock_irqrestore(&uic->lock, flags); +} + +static void uic_mask_irq(unsigned int virq) +{ + struct uic *uic = get_irq_chip_data(virq); + unsigned int src = uic_irq_to_hw(virq); + unsigned long flags; + u32 er; + + spin_lock_irqsave(&uic->lock, flags); + er = mfdcr(uic->dcrbase + UIC_ER); + er &= ~(1 << (31 - src)); + mtdcr(uic->dcrbase + UIC_ER, er); + spin_unlock_irqrestore(&uic->lock, flags); +} + +static void uic_ack_irq(unsigned int virq) +{ + struct uic *uic = get_irq_chip_data(virq); + unsigned int src = uic_irq_to_hw(virq); + unsigned long flags; + + spin_lock_irqsave(&uic->lock, flags); + mtdcr(uic->dcrbase + UIC_SR, 1 << (31-src)); + spin_unlock_irqrestore(&uic->lock, flags); +} + +static int uic_set_irq_type(unsigned int virq, unsigned int flow_type) +{ + struct uic *uic = get_irq_chip_data(virq); + unsigned int src = uic_irq_to_hw(virq); + struct irq_desc *desc = get_irq_desc(virq); + unsigned long flags; + int trigger, polarity; + u32 tr, pr, mask; + + switch (flow_type & IRQ_TYPE_SENSE_MASK) { + case IRQ_TYPE_NONE: + uic_mask_irq(virq); + return 0; + + case IRQ_TYPE_EDGE_RISING: + trigger = 1; polarity = 1; + break; + case IRQ_TYPE_EDGE_FALLING: + trigger = 1; polarity = 0; + break; + case IRQ_TYPE_LEVEL_HIGH: + trigger = 0; polarity = 1; + break; + case IRQ_TYPE_LEVEL_LOW: + trigger = 0; polarity = 0; + break; + default: + return -EINVAL; + } + + mask = ~(1 << (31 - src)); + + spin_lock_irqsave(&uic->lock, flags); + tr = mfdcr(uic->dcrbase + UIC_TR); + pr = mfdcr(uic->dcrbase + UIC_PR); + tr = (tr & mask) | (trigger << (31-src)); + pr = (pr & mask) | (polarity << (31-src)); + + mtdcr(uic->dcrbase + UIC_PR, pr); + mtdcr(uic->dcrbase + UIC_TR, tr); + + desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); + desc->status |= flow_type & IRQ_TYPE_SENSE_MASK; + if (trigger) + desc->status |= IRQ_LEVEL; + + spin_unlock_irqrestore(&uic->lock, flags); + + return 0; +} + +static struct irq_chip uic_irq_chip = { + .typename = " UIC ", + .unmask = uic_unmask_irq, + .mask = uic_mask_irq, +/* .mask_ack = uic_mask_irq_and_ack, */ + .ack = uic_ack_irq, + .set_type = uic_set_irq_type, +}; + +static int uic_host_match(struct irq_host *h, struct device_node *node) +{ + struct uic *uic = h->host_data; + return uic->of_node == node; +} + +static int uic_host_map(struct irq_host *h, unsigned int virq, + irq_hw_number_t hw) +{ + struct uic *uic = h->host_data; + + set_irq_chip_data(virq, uic); + /* Despite the name, handle_level_irq() works for both level + * and edge irqs on UIC. FIXME: check this is correct */ + set_irq_chip_and_handler(virq, &uic_irq_chip, handle_level_irq); + + /* Set default irq type */ + set_irq_type(virq, IRQ_TYPE_NONE); + + return 0; +} + +static int uic_host_xlate(struct irq_host *h, struct device_node *ct, + u32 *intspec, unsigned int intsize, + irq_hw_number_t *out_hwirq, unsigned int *out_type) + +{ + /* UIC intspecs must have 2 cells */ + BUG_ON(intsize != 2); + *out_hwirq = intspec[0]; + *out_type = intspec[1]; + return 0; +} + +static struct irq_host_ops uic_host_ops = { + .match = uic_host_match, + .map = uic_host_map, + .xlate = uic_host_xlate, +}; + +irqreturn_t uic_cascade(int virq, void *data) +{ + struct uic *uic = data; + u32 msr; + int src; + int subvirq; + + msr = mfdcr(uic->dcrbase + UIC_MSR); + src = 32 - ffs(msr); + + subvirq = irq_linear_revmap(uic->irqhost, src); + generic_handle_irq(subvirq); + + return IRQ_HANDLED; +} + +static struct uic * __init uic_init_one(struct device_node *node) +{ + struct uic *uic; + const u32 *indexp, *dcrreg; + int len; + + BUG_ON(! device_is_compatible(node, "ibm,uic")); + + uic = alloc_bootmem(sizeof(*uic)); + if (! uic) + return NULL; /* FIXME: panic? */ + + memset(uic, 0, sizeof(*uic)); + spin_lock_init(&uic->lock); + uic->of_node = of_node_get(node); + indexp = of_get_property(node, "cell-index", &len); + if (!indexp || (len != sizeof(u32))) { + printk(KERN_ERR "uic: Device node %s has missing or invalid " + "cell-index property\n", node->full_name); + return NULL; + } + uic->index = *indexp; + + dcrreg = of_get_property(node, "dcr-reg", &len); + if (!dcrreg || (len != 2*sizeof(u32))) { + printk(KERN_ERR "uic: Device node %s has missing or invalid " + "dcr-reg property\n", node->full_name); + return NULL; + } + uic->dcrbase = *dcrreg; + + uic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, NR_UIC_INTS, + &uic_host_ops, -1); + if (! uic->irqhost) { + of_node_put(node); + return NULL; /* FIXME: panic? */ + } + + uic->irqhost->host_data = uic; + + /* Start with all interrupts disabled, level and non-critical */ + mtdcr(uic->dcrbase + UIC_ER, 0); + mtdcr(uic->dcrbase + UIC_CR, 0); + mtdcr(uic->dcrbase + UIC_TR, 0); + /* Clear any pending interrupts, in case the firmware left some */ + mtdcr(uic->dcrbase + UIC_SR, 0xffffffff); + + printk ("UIC%d (%d IRQ sources) at DCR 0x%x\n", uic->index, + NR_UIC_INTS, uic->dcrbase); + + return uic; +} + +void __init uic_init_tree(void) +{ + struct device_node *np; + struct uic *uic; + const u32 *interrupts; + + /* First locate and initialize the top-level UIC */ + + np = of_find_compatible_node(NULL, NULL, "ibm,uic"); + while (np) { + interrupts = of_get_property(np, "interrupts", NULL); + if (! interrupts) + break; + + np = of_find_compatible_node(np, NULL, "ibm,uic"); + } + + BUG_ON(!np); /* uic_init_tree() assumes there's a UIC as the + * top-level interrupt controller */ + primary_uic = uic_init_one(np); + if (! primary_uic) + panic("Unable to initialize primary UIC %s\n", np->full_name); + + irq_set_default_host(primary_uic->irqhost); + of_node_put(np); + + /* The scan again for cascaded UICs */ + np = of_find_compatible_node(NULL, NULL, "ibm,uic"); + while (np) { + interrupts = of_get_property(np, "interrupts", NULL); + if (interrupts) { + /* Secondary UIC */ + int cascade_virq; + int ret; + + uic = uic_init_one(np); + if (! uic) + panic("Unable to initialize a secondary UIC %s\n", + np->full_name); + + cascade_virq = irq_of_parse_and_map(np, 0); + + uic->cascade.handler = uic_cascade; + uic->cascade.name = "UIC cascade"; + uic->cascade.dev_id = uic; + + ret = setup_irq(cascade_virq, &uic->cascade); + if (ret) + printk(KERN_ERR "Failed to setup_irq(%d) for " + "UIC%d cascade\n", cascade_virq, + uic->index); + + /* FIXME: setup critical cascade?? */ + } + + np = of_find_compatible_node(np, NULL, "ibm,uic"); + } +} + +/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */ +unsigned int uic_get_irq(void) +{ + u32 msr; + int src; + + BUG_ON(! primary_uic); + + msr = mfdcr(primary_uic->dcrbase + UIC_MSR); + src = 32 - ffs(msr); + + return irq_linear_revmap(primary_uic->irqhost, src); +} diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index bf299b6..b481db1 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -330,18 +330,17 @@ static void release_output_lock(void) static int xmon_core(struct pt_regs *regs, int fromipi) { int cmd = 0; - unsigned long msr; struct bpt *bp; long recurse_jmp[JMP_BUF_LEN]; unsigned long offset; + unsigned long flags; #ifdef CONFIG_SMP int cpu; int secondary; unsigned long timeout; #endif - msr = mfmsr(); - mtmsr(msr & ~MSR_EE); /* disable interrupts */ + local_irq_save(flags); bp = in_breakpoint_table(regs->nip, &offset); if (bp != NULL) { @@ -516,7 +515,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi) insert_cpu_bpts(); - mtmsr(msr); /* restore interrupt enable */ + local_irq_restore(flags); return cmd != 'X' && cmd != EOF; } @@ -1360,8 +1359,12 @@ static void print_bug_trap(struct pt_regs *regs) if (is_warning_bug(bug)) return; +#ifdef CONFIG_DEBUG_BUGVERBOSE printf("kernel BUG at %s:%u!\n", bug->file, bug->line); +#else + printf("kernel BUG at %p!\n", (void *)bug->bug_addr); +#endif } void excprint(struct pt_regs *fp) diff --git a/arch/ppc/8xx_io/Kconfig b/arch/ppc/8xx_io/Kconfig index 57dacf9..c623e44 100644 --- a/arch/ppc/8xx_io/Kconfig +++ b/arch/ppc/8xx_io/Kconfig @@ -74,10 +74,6 @@ config ENET_BIG_BUFFERS Allocate large buffers for MPC8xx Ethernet. Increases throughput and decreases the likelihood of dropped packets, but costs memory. -config HTDMSOUND - bool "Embedded Planet HIOX Audio" - depends on SOUND=y - # This doesn't really belong here, but it is convenient to ask # 8xx specific questions. comment "Generic MPC8xx Options" diff --git a/arch/ppc/8xx_io/Makefile b/arch/ppc/8xx_io/Makefile index d876018..1051a06 100644 --- a/arch/ppc/8xx_io/Makefile +++ b/arch/ppc/8xx_io/Makefile @@ -7,4 +7,3 @@ obj-y := commproc.o obj-$(CONFIG_FEC_ENET) += fec.o obj-$(CONFIG_SCC_ENET) += enet.o obj-$(CONFIG_UCODE_PATCH) += micropatch.o -obj-$(CONFIG_HTDMSOUND) += cs4218_tdm.o diff --git a/arch/ppc/8xx_io/cs4218.h b/arch/ppc/8xx_io/cs4218.h deleted file mode 100644 index e5f9430..0000000 --- a/arch/ppc/8xx_io/cs4218.h +++ /dev/null @@ -1,166 +0,0 @@ -#ifndef _cs4218_h_ -/* - * Hacked version of linux/drivers/sound/dmasound/dmasound.h - * - * - * Minor numbers for the sound driver. - * - * Unfortunately Creative called the codec chip of SB as a DSP. For this - * reason the /dev/dsp is reserved for digitized audio use. There is a - * device for true DSP processors but it will be called something else. - * In v3.0 it's /dev/sndproc but this could be a temporary solution. - */ -#define _cs4218_h_ - -#include <linux/types.h> - -#define SND_NDEVS 256 /* Number of supported devices */ -#define SND_DEV_CTL 0 /* Control port /dev/mixer */ -#define SND_DEV_SEQ 1 /* Sequencer output /dev/sequencer (FM - synthesizer and MIDI output) */ -#define SND_DEV_MIDIN 2 /* Raw midi access */ -#define SND_DEV_DSP 3 /* Digitized voice /dev/dsp */ -#define SND_DEV_AUDIO 4 /* Sparc compatible /dev/audio */ -#define SND_DEV_DSP16 5 /* Like /dev/dsp but 16 bits/sample */ -#define SND_DEV_STATUS 6 /* /dev/sndstat */ -/* #7 not in use now. Was in 2.4. Free for use after v3.0. */ -#define SND_DEV_SEQ2 8 /* /dev/sequencer, level 2 interface */ -#define SND_DEV_SNDPROC 9 /* /dev/sndproc for programmable devices */ -#define SND_DEV_PSS SND_DEV_SNDPROC - -/* switch on various prinks */ -#define DEBUG_DMASOUND 1 - -#define MAX_AUDIO_DEV 5 -#define MAX_MIXER_DEV 4 -#define MAX_SYNTH_DEV 3 -#define MAX_MIDI_DEV 6 -#define MAX_TIMER_DEV 3 - -#define MAX_CATCH_RADIUS 10 - -#define le2be16(x) (((x)<<8 & 0xff00) | ((x)>>8 & 0x00ff)) -#define le2be16dbl(x) (((x)<<8 & 0xff00ff00) | ((x)>>8 & 0x00ff00ff)) - -#define IOCTL_IN(arg, ret) \ - do { int error = get_user(ret, (int *)(arg)); \ - if (error) return error; \ - } while (0) -#define IOCTL_OUT(arg, ret) ioctl_return((int *)(arg), ret) - -static inline int ioctl_return(int *addr, int value) -{ - return value < 0 ? value : put_user(value, addr); -} - -#define HAS_RECORD - - /* - * Initialization - */ - -/* description of the set-up applies to either hard or soft settings */ - -typedef struct { - int format; /* AFMT_* */ - int stereo; /* 0 = mono, 1 = stereo */ - int size; /* 8/16 bit*/ - int speed; /* speed */ -} SETTINGS; - - /* - * Machine definitions - */ - -typedef struct { - const char *name; - const char *name2; - void (*open)(void); - void (*release)(void); - void *(*dma_alloc)(unsigned int, gfp_t); - void (*dma_free)(void *, unsigned int); - int (*irqinit)(void); -#ifdef MODULE - void (*irqcleanup)(void); -#endif - void (*init)(void); - void (*silence)(void); - int (*setFormat)(int); - int (*setVolume)(int); - int (*setBass)(int); - int (*setTreble)(int); - int (*setGain)(int); - void (*play)(void); - void (*record)(void); /* optional */ - void (*mixer_init)(void); /* optional */ - int (*mixer_ioctl)(u_int, u_long); /* optional */ - int (*write_sq_setup)(void); /* optional */ - int (*read_sq_setup)(void); /* optional */ - int (*sq_open)(mode_t); /* optional */ - int (*state_info)(char *, size_t); /* optional */ - void (*abort_read)(void); /* optional */ - int min_dsp_speed; - int max_dsp_speed; - int version ; - int hardware_afmts ; /* OSS says we only return h'ware info */ - /* when queried via SNDCTL_DSP_GETFMTS */ - int capabilities ; /* low-level reply to SNDCTL_DSP_GETCAPS */ - SETTINGS default_hard ; /* open() or init() should set something valid */ - SETTINGS default_soft ; /* you can make it look like old OSS, if you want to */ -} MACHINE; - - /* - * Low level stuff - */ - -typedef struct { - ssize_t (*ct_ulaw)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_alaw)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_s8)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_u8)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_s16be)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_u16be)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_s16le)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_u16le)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); -} TRANS; - - - /* - * Sound queue stuff, the heart of the driver - */ - -struct sound_queue { - /* buffers allocated for this queue */ - int numBufs; /* real limits on what the user can have */ - int bufSize; /* in bytes */ - char **buffers; - - /* current parameters */ - int locked ; /* params cannot be modified when != 0 */ - int user_frags ; /* user requests this many */ - int user_frag_size ; /* of this size */ - int max_count; /* actual # fragments <= numBufs */ - int block_size; /* internal block size in bytes */ - int max_active; /* in-use fragments <= max_count */ - - /* it shouldn't be necessary to declare any of these volatile */ - int front, rear, count; - int rear_size; - /* - * The use of the playing field depends on the hardware - * - * Atari, PMac: The number of frames that are loaded/playing - * - * Amiga: Bit 0 is set: a frame is loaded - * Bit 1 is set: a frame is playing - */ - int active; - wait_queue_head_t action_queue, open_queue, sync_queue; - int open_mode; - int busy, syncing, xruns, died; -}; - -#define SLEEP(queue) interruptible_sleep_on_timeout(&queue, HZ) -#define WAKE_UP(queue) (wake_up_interruptible(&queue)) - -#endif /* _cs4218_h_ */ diff --git a/arch/ppc/8xx_io/cs4218_tdm.c b/arch/ppc/8xx_io/cs4218_tdm.c deleted file mode 100644 index a956f28..0000000 --- a/arch/ppc/8xx_io/cs4218_tdm.c +++ /dev/null @@ -1,2833 +0,0 @@ - -/* This is a modified version of linux/drivers/sound/dmasound.c to - * support the CS4218 codec on the 8xx TDM port. Thanks to everyone - * that contributed to the dmasound software (which includes me :-). - * - * The CS4218 is configured in Mode 4, sub-mode 0. This provides - * left/right data only on the TDM port, as a 32-bit word, per frame - * pulse. The control of the CS4218 is provided by some other means, - * like the SPI port. - * Dan Malek (dmalek@jlc.net) - */ - -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/timer.h> -#include <linux/major.h> -#include <linux/fcntl.h> -#include <linux/errno.h> -#include <linux/mm.h> -#include <linux/slab.h> -#include <linux/sound.h> -#include <linux/init.h> -#include <linux/delay.h> - -#include <asm/system.h> -#include <asm/irq.h> -#include <asm/pgtable.h> -#include <asm/uaccess.h> -#include <asm/io.h> - -/* Should probably do something different with this path name..... - * Actually, I should just stop using it... - */ -#include "cs4218.h" -#include <linux/soundcard.h> - -#include <asm/mpc8xx.h> -#include <asm/8xx_immap.h> -#include <asm/commproc.h> - -#define DMASND_CS4218 5 - -#define MAX_CATCH_RADIUS 10 -#define MIN_BUFFERS 4 -#define MIN_BUFSIZE 4 -#define MAX_BUFSIZE 128 - -#define HAS_8BIT_TABLES - -static int sq_unit = -1; -static int mixer_unit = -1; -static int state_unit = -1; -static int irq_installed = 0; -static char **sound_buffers = NULL; -static char **sound_read_buffers = NULL; - -static DEFINE_SPINLOCK(cs4218_lock); - -/* Local copies of things we put in the control register. Output - * volume, like most codecs is really attenuation. - */ -static int cs4218_rate_index; - -/* - * Stuff for outputting a beep. The values range from -327 to +327 - * so we can multiply by an amplitude in the range 0..100 to get a - * signed short value to put in the output buffer. - */ -static short beep_wform[256] = { - 0, 40, 79, 117, 153, 187, 218, 245, - 269, 288, 304, 316, 323, 327, 327, 324, - 318, 310, 299, 288, 275, 262, 249, 236, - 224, 213, 204, 196, 190, 186, 183, 182, - 182, 183, 186, 189, 192, 196, 200, 203, - 206, 208, 209, 209, 209, 207, 204, 201, - 197, 193, 188, 183, 179, 174, 170, 166, - 163, 161, 160, 159, 159, 160, 161, 162, - 164, 166, 168, 169, 171, 171, 171, 170, - 169, 167, 163, 159, 155, 150, 144, 139, - 133, 128, 122, 117, 113, 110, 107, 105, - 103, 103, 103, 103, 104, 104, 105, 105, - 105, 103, 101, 97, 92, 86, 78, 68, - 58, 45, 32, 18, 3, -11, -26, -41, - -55, -68, -79, -88, -95, -100, -102, -102, - -99, -93, -85, -75, -62, -48, -33, -16, - 0, 16, 33, 48, 62, 75, 85, 93, - 99, 102, 102, 100, 95, 88, 79, 68, - 55, 41, 26, 11, -3, -18, -32, -45, - -58, -68, -78, -86, -92, -97, -101, -103, - -105, -105, -105, -104, -104, -103, -103, -103, - -103, -105, -107, -110, -113, -117, -122, -128, - -133, -139, -144, -150, -155, -159, -163, -167, - -169, -170, -171, -171, -171, -169, -168, -166, - -164, -162, -161, -160, -159, -159, -160, -161, - -163, -166, -170, -174, -179, -183, -188, -193, - -197, -201, -204, -207, -209, -209, -209, -208, - -206, -203, -200, -196, -192, -189, -186, -183, - -182, -182, -183, -186, -190, -196, -204, -213, - -224, -236, -249, -262, -275, -288, -299, -310, - -318, -324, -327, -327, -323, -316, -304, -288, - -269, -245, -218, -187, -153, -117, -79, -40, -}; - -#define BEEP_SPEED 5 /* 22050 Hz sample rate */ -#define BEEP_BUFLEN 512 -#define BEEP_VOLUME 15 /* 0 - 100 */ - -static int beep_volume = BEEP_VOLUME; -static int beep_playing = 0; -static int beep_state = 0; -static short *beep_buf; -static void (*orig_mksound)(unsigned int, unsigned int); - -/* This is found someplace else......I guess in the keyboard driver - * we don't include. - */ -static void (*kd_mksound)(unsigned int, unsigned int); - -static int catchRadius = 0; -static int numBufs = 4, bufSize = 32; -static int numReadBufs = 4, readbufSize = 32; - - -/* TDM/Serial transmit and receive buffer descriptors. -*/ -static volatile cbd_t *rx_base, *rx_cur, *tx_base, *tx_cur; - -module_param(catchRadius, int, 0); -module_param(numBufs, int, 0); -module_param(bufSize, int, 0); -module_param(numreadBufs, int, 0); -module_param(readbufSize, int, 0); - -#define arraysize(x) (sizeof(x)/sizeof(*(x))) -#define le2be16(x) (((x)<<8 & 0xff00) | ((x)>>8 & 0x00ff)) -#define le2be16dbl(x) (((x)<<8 & 0xff00ff00) | ((x)>>8 & 0x00ff00ff)) - -#define IOCTL_IN(arg, ret) \ - do { int error = get_user(ret, (int *)(arg)); \ - if (error) return error; \ - } while (0) -#define IOCTL_OUT(arg, ret) ioctl_return((int *)(arg), ret) - -/* CS4218 serial port control in mode 4. -*/ -#define CS_INTMASK ((uint)0x40000000) -#define CS_DO1 ((uint)0x20000000) -#define CS_LATTEN ((uint)0x1f000000) -#define CS_RATTEN ((uint)0x00f80000) -#define CS_MUTE ((uint)0x00040000) -#define CS_ISL ((uint)0x00020000) -#define CS_ISR ((uint)0x00010000) -#define CS_LGAIN ((uint)0x0000f000) -#define CS_RGAIN ((uint)0x00000f00) - -#define CS_LATTEN_SET(X) (((X) & 0x1f) << 24) -#define CS_RATTEN_SET(X) (((X) & 0x1f) << 19) -#define CS_LGAIN_SET(X) (((X) & 0x0f) << 12) -#define CS_RGAIN_SET(X) (((X) & 0x0f) << 8) - -#define CS_LATTEN_GET(X) (((X) >> 24) & 0x1f) -#define CS_RATTEN_GET(X) (((X) >> 19) & 0x1f) -#define CS_LGAIN_GET(X) (((X) >> 12) & 0x0f) -#define CS_RGAIN_GET(X) (((X) >> 8) & 0x0f) - -/* The control register is effectively write only. We have to keep a copy - * of what we write. - */ -static uint cs4218_control; - -/* A place to store expanding information. -*/ -static int expand_bal; -static int expand_data; - -/* Since I can't make the microcode patch work for the SPI, I just - * clock the bits using software. - */ -static void sw_spi_init(void); -static void sw_spi_io(u_char *obuf, u_char *ibuf, uint bcnt); -static uint cs4218_ctl_write(uint ctlreg); - -/*** Some low level helpers **************************************************/ - -/* 16 bit mu-law */ - -static short ulaw2dma16[] = { - -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956, - -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764, - -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412, - -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316, - -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140, - -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, - -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004, - -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, - -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436, - -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, - -876, -844, -812, -780, -748, -716, -684, -652, - -620, -588, -556, -524, -492, -460, -428, -396, - -372, -356, -340, -324, -308, -292, -276, -260, - -244, -228, -212, -196, -180, -164, -148, -132, - -120, -112, -104, -96, -88, -80, -72, -64, - -56, -48, -40, -32, -24, -16, -8, 0, - 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956, - 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, - 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412, - 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316, - 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140, - 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092, - 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004, - 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980, - 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436, - 1372, 1308, 1244, 1180, 1116, 1052, 988, 924, - 876, 844, 812, 780, 748, 716, 684, 652, - 620, 588, 556, 524, 492, 460, 428, 396, - 372, 356, 340, 324, 308, 292, 276, 260, - 244, 228, 212, 196, 180, 164, 148, 132, - 120, 112, 104, 96, 88, 80, 72, 64, - 56, 48, 40, 32, 24, 16, 8, 0, -}; - -/* 16 bit A-law */ - -static short alaw2dma16[] = { - -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, - -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, - -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, - -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, - -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944, - -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136, - -11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472, - -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568, - -344, -328, -376, -360, -280, -264, -312, -296, - -472, -456, -504, -488, -408, -392, -440, -424, - -88, -72, -120, -104, -24, -8, -56, -40, - -216, -200, -248, -232, -152, -136, -184, -168, - -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184, - -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, - -688, -656, -752, -720, -560, -528, -624, -592, - -944, -912, -1008, -976, -816, -784, -880, -848, - 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, - 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, - 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, - 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, - 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, - 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, - 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, - 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, - 344, 328, 376, 360, 280, 264, 312, 296, - 472, 456, 504, 488, 408, 392, 440, 424, - 88, 72, 120, 104, 24, 8, 56, 40, - 216, 200, 248, 232, 152, 136, 184, 168, - 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, - 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, - 688, 656, 752, 720, 560, 528, 624, 592, - 944, 912, 1008, 976, 816, 784, 880, 848, -}; - - -/*** Translations ************************************************************/ - - -static ssize_t cs4218_ct_law(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t cs4218_ct_s8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t cs4218_ct_u8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t cs4218_ct_s16(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t cs4218_ct_u16(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t cs4218_ctx_law(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t cs4218_ctx_s8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t cs4218_ctx_u8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t cs4218_ctx_s16(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t cs4218_ctx_u16(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t cs4218_ct_s16_read(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t cs4218_ct_u16_read(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); - - -/*** Low level stuff *********************************************************/ - -struct cs_sound_settings { - MACHINE mach; /* machine dependent things */ - SETTINGS hard; /* hardware settings */ - SETTINGS soft; /* software settings */ - SETTINGS dsp; /* /dev/dsp default settings */ - TRANS *trans_write; /* supported translations for playback */ - TRANS *trans_read; /* supported translations for record */ - int volume_left; /* volume (range is machine dependent) */ - int volume_right; - int bass; /* tone (range is machine dependent) */ - int treble; - int gain; - int minDev; /* minor device number currently open */ -}; - -static struct cs_sound_settings sound; - -static void *CS_Alloc(unsigned int size, gfp_t flags); -static void CS_Free(void *ptr, unsigned int size); -static int CS_IrqInit(void); -#ifdef MODULE -static void CS_IrqCleanup(void); -#endif /* MODULE */ -static void CS_Silence(void); -static void CS_Init(void); -static void CS_Play(void); -static void CS_Record(void); -static int CS_SetFormat(int format); -static int CS_SetVolume(int volume); -static void cs4218_tdm_tx_intr(void *devid); -static void cs4218_tdm_rx_intr(void *devid); -static void cs4218_intr(void *devid); -static int cs_get_volume(uint reg); -static int cs_volume_setter(int volume, int mute); -static int cs_get_gain(uint reg); -static int cs_set_gain(int gain); -static void cs_mksound(unsigned int hz, unsigned int ticks); -static void cs_nosound(unsigned long xx); - -/*** Mid level stuff *********************************************************/ - - -static void sound_silence(void); -static void sound_init(void); -static int sound_set_format(int format); -static int sound_set_speed(int speed); -static int sound_set_stereo(int stereo); -static int sound_set_volume(int volume); - -static ssize_t sound_copy_translate(const u_char *userPtr, - size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t sound_copy_translate_read(const u_char *userPtr, - size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); - - -/* - * /dev/mixer abstraction - */ - -struct sound_mixer { - int busy; - int modify_counter; -}; - -static struct sound_mixer mixer; - -static struct sound_queue sq; -static struct sound_queue read_sq; - -#define sq_block_address(i) (sq.buffers[i]) -#define SIGNAL_RECEIVED (signal_pending(current)) -#define NON_BLOCKING(open_mode) (open_mode & O_NONBLOCK) -#define ONE_SECOND HZ /* in jiffies (100ths of a second) */ -#define NO_TIME_LIMIT 0xffffffff - -/* - * /dev/sndstat - */ - -struct sound_state { - int busy; - char buf[512]; - int len, ptr; -}; - -static struct sound_state state; - -/*** Common stuff ********************************************************/ - -static long long sound_lseek(struct file *file, long long offset, int orig); - -/*** Config & Setup **********************************************************/ - -void dmasound_setup(char *str, int *ints); - -/*** Translations ************************************************************/ - - -/* ++TeSche: radically changed for new expanding purposes... - * - * These two routines now deal with copying/expanding/translating the samples - * from user space into our buffer at the right frequency. They take care about - * how much data there's actually to read, how much buffer space there is and - * to convert samples into the right frequency/encoding. They will only work on - * complete samples so it may happen they leave some bytes in the input stream - * if the user didn't write a multiple of the current sample size. They both - * return the number of bytes they've used from both streams so you may detect - * such a situation. Luckily all programs should be able to cope with that. - * - * I think I've optimized anything as far as one can do in plain C, all - * variables should fit in registers and the loops are really short. There's - * one loop for every possible situation. Writing a more generalized and thus - * parameterized loop would only produce slower code. Feel free to optimize - * this in assembler if you like. :) - * - * I think these routines belong here because they're not yet really hardware - * independent, especially the fact that the Falcon can play 16bit samples - * only in stereo is hardcoded in both of them! - * - * ++geert: split in even more functions (one per format) - */ - -static ssize_t cs4218_ct_law(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - short *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma16: alaw2dma16; - ssize_t count, used; - short *p = (short *) &frame[*frameUsed]; - int val, stereo = sound.soft.stereo; - - frameLeft >>= 2; - if (stereo) - userCount >>= 1; - used = count = min(userCount, frameLeft); - while (count > 0) { - u_char data; - if (get_user(data, userPtr++)) - return -EFAULT; - val = table[data]; - *p++ = val; - if (stereo) { - if (get_user(data, userPtr++)) - return -EFAULT; - val = table[data]; - } - *p++ = val; - count--; - } - *frameUsed += used * 4; - return stereo? used * 2: used; -} - - -static ssize_t cs4218_ct_s8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - short *p = (short *) &frame[*frameUsed]; - int val, stereo = sound.soft.stereo; - - frameLeft >>= 2; - if (stereo) - userCount >>= 1; - used = count = min(userCount, frameLeft); - while (count > 0) { - u_char data; - if (get_user(data, userPtr++)) - return -EFAULT; - val = data << 8; - *p++ = val; - if (stereo) { - if (get_user(data, userPtr++)) - return -EFAULT; - val = data << 8; - } - *p++ = val; - count--; - } - *frameUsed += used * 4; - return stereo? used * 2: used; -} - - -static ssize_t cs4218_ct_u8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - short *p = (short *) &frame[*frameUsed]; - int val, stereo = sound.soft.stereo; - - frameLeft >>= 2; - if (stereo) - userCount >>= 1; - used = count = min(userCount, frameLeft); - while (count > 0) { - u_char data; - if (get_user(data, userPtr++)) - return -EFAULT; - val = (data ^ 0x80) << 8; - *p++ = val; - if (stereo) { - if (get_user(data, userPtr++)) - return -EFAULT; - val = (data ^ 0x80) << 8; - } - *p++ = val; - count--; - } - *frameUsed += used * 4; - return stereo? used * 2: used; -} - - -/* This is the default format of the codec. Signed, 16-bit stereo - * generated by an application shouldn't have to be copied at all. - * We should just get the phsical address of the buffers and update - * the TDM BDs directly. - */ -static ssize_t cs4218_ct_s16(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - int stereo = sound.soft.stereo; - short *fp = (short *) &frame[*frameUsed]; - - frameLeft >>= 2; - userCount >>= (stereo? 2: 1); - used = count = min(userCount, frameLeft); - if (!stereo) { - short *up = (short *) userPtr; - while (count > 0) { - short data; - if (get_user(data, up++)) - return -EFAULT; - *fp++ = data; - *fp++ = data; - count--; - } - } else { - if (copy_from_user(fp, userPtr, count * 4)) - return -EFAULT; - } - *frameUsed += used * 4; - return stereo? used * 4: used * 2; -} - -static ssize_t cs4218_ct_u16(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - int mask = (sound.soft.format == AFMT_U16_LE? 0x0080: 0x8000); - int stereo = sound.soft.stereo; - short *fp = (short *) &frame[*frameUsed]; - short *up = (short *) userPtr; - - frameLeft >>= 2; - userCount >>= (stereo? 2: 1); - used = count = min(userCount, frameLeft); - while (count > 0) { - int data; - if (get_user(data, up++)) - return -EFAULT; - data ^= mask; - *fp++ = data; - if (stereo) { - if (get_user(data, up++)) - return -EFAULT; - data ^= mask; - } - *fp++ = data; - count--; - } - *frameUsed += used * 4; - return stereo? used * 4: used * 2; -} - - -static ssize_t cs4218_ctx_law(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - unsigned short *table = (unsigned short *) - (sound.soft.format == AFMT_MU_LAW ? ulaw2dma16: alaw2dma16); - unsigned int data = expand_data; - unsigned int *p = (unsigned int *) &frame[*frameUsed]; - int bal = expand_bal; - int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - int utotal, ftotal; - int stereo = sound.soft.stereo; - - frameLeft >>= 2; - if (stereo) - userCount >>= 1; - ftotal = frameLeft; - utotal = userCount; - while (frameLeft) { - u_char c; - if (bal < 0) { - if (userCount == 0) - break; - if (get_user(c, userPtr++)) - return -EFAULT; - data = table[c]; - if (stereo) { - if (get_user(c, userPtr++)) - return -EFAULT; - data = (data << 16) + table[c]; - } else - data = (data << 16) + data; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - expand_bal = bal; - expand_data = data; - *frameUsed += (ftotal - frameLeft) * 4; - utotal -= userCount; - return stereo? utotal * 2: utotal; -} - - -static ssize_t cs4218_ctx_s8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - unsigned int *p = (unsigned int *) &frame[*frameUsed]; - unsigned int data = expand_data; - int bal = expand_bal; - int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - int stereo = sound.soft.stereo; - int utotal, ftotal; - - frameLeft >>= 2; - if (stereo) - userCount >>= 1; - ftotal = frameLeft; - utotal = userCount; - while (frameLeft) { - u_char c; - if (bal < 0) { - if (userCount == 0) - break; - if (get_user(c, userPtr++)) - return -EFAULT; - data = c << 8; - if (stereo) { - if (get_user(c, userPtr++)) - return -EFAULT; - data = (data << 16) + (c << 8); - } else - data = (data << 16) + data; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - expand_bal = bal; - expand_data = data; - *frameUsed += (ftotal - frameLeft) * 4; - utotal -= userCount; - return stereo? utotal * 2: utotal; -} - - -static ssize_t cs4218_ctx_u8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - unsigned int *p = (unsigned int *) &frame[*frameUsed]; - unsigned int data = expand_data; - int bal = expand_bal; - int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - int stereo = sound.soft.stereo; - int utotal, ftotal; - - frameLeft >>= 2; - if (stereo) - userCount >>= 1; - ftotal = frameLeft; - utotal = userCount; - while (frameLeft) { - u_char c; - if (bal < 0) { - if (userCount == 0) - break; - if (get_user(c, userPtr++)) - return -EFAULT; - data = (c ^ 0x80) << 8; - if (stereo) { - if (get_user(c, userPtr++)) - return -EFAULT; - data = (data << 16) + ((c ^ 0x80) << 8); - } else - data = (data << 16) + data; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - expand_bal = bal; - expand_data = data; - *frameUsed += (ftotal - frameLeft) * 4; - utotal -= userCount; - return stereo? utotal * 2: utotal; -} - - -static ssize_t cs4218_ctx_s16(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - unsigned int *p = (unsigned int *) &frame[*frameUsed]; - unsigned int data = expand_data; - unsigned short *up = (unsigned short *) userPtr; - int bal = expand_bal; - int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - int stereo = sound.soft.stereo; - int utotal, ftotal; - - frameLeft >>= 2; - userCount >>= (stereo? 2: 1); - ftotal = frameLeft; - utotal = userCount; - while (frameLeft) { - unsigned short c; - if (bal < 0) { - if (userCount == 0) - break; - if (get_user(data, up++)) - return -EFAULT; - if (stereo) { - if (get_user(c, up++)) - return -EFAULT; - data = (data << 16) + c; - } else - data = (data << 16) + data; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - expand_bal = bal; - expand_data = data; - *frameUsed += (ftotal - frameLeft) * 4; - utotal -= userCount; - return stereo? utotal * 4: utotal * 2; -} - - -static ssize_t cs4218_ctx_u16(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - int mask = (sound.soft.format == AFMT_U16_LE? 0x0080: 0x8000); - unsigned int *p = (unsigned int *) &frame[*frameUsed]; - unsigned int data = expand_data; - unsigned short *up = (unsigned short *) userPtr; - int bal = expand_bal; - int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - int stereo = sound.soft.stereo; - int utotal, ftotal; - - frameLeft >>= 2; - userCount >>= (stereo? 2: 1); - ftotal = frameLeft; - utotal = userCount; - while (frameLeft) { - unsigned short c; - if (bal < 0) { - if (userCount == 0) - break; - if (get_user(data, up++)) - return -EFAULT; - data ^= mask; - if (stereo) { - if (get_user(c, up++)) - return -EFAULT; - data = (data << 16) + (c ^ mask); - } else - data = (data << 16) + data; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - expand_bal = bal; - expand_data = data; - *frameUsed += (ftotal - frameLeft) * 4; - utotal -= userCount; - return stereo? utotal * 4: utotal * 2; -} - -static ssize_t cs4218_ct_s8_read(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - short *p = (short *) &frame[*frameUsed]; - int val, stereo = sound.soft.stereo; - - frameLeft >>= 2; - if (stereo) - userCount >>= 1; - used = count = min(userCount, frameLeft); - while (count > 0) { - u_char data; - - val = *p++; - data = val >> 8; - if (put_user(data, (u_char *)userPtr++)) - return -EFAULT; - if (stereo) { - val = *p; - data = val >> 8; - if (put_user(data, (u_char *)userPtr++)) - return -EFAULT; - } - p++; - count--; - } - *frameUsed += used * 4; - return stereo? used * 2: used; -} - - -static ssize_t cs4218_ct_u8_read(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - short *p = (short *) &frame[*frameUsed]; - int val, stereo = sound.soft.stereo; - - frameLeft >>= 2; - if (stereo) - userCount >>= 1; - used = count = min(userCount, frameLeft); - while (count > 0) { - u_char data; - - val = *p++; - data = (val >> 8) ^ 0x80; - if (put_user(data, (u_char *)userPtr++)) - return -EFAULT; - if (stereo) { - val = *p; - data = (val >> 8) ^ 0x80; - if (put_user(data, (u_char *)userPtr++)) - return -EFAULT; - } - p++; - count--; - } - *frameUsed += used * 4; - return stereo? used * 2: used; -} - - -static ssize_t cs4218_ct_s16_read(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - int stereo = sound.soft.stereo; - short *fp = (short *) &frame[*frameUsed]; - - frameLeft >>= 2; - userCount >>= (stereo? 2: 1); - used = count = min(userCount, frameLeft); - if (!stereo) { - short *up = (short *) userPtr; - while (count > 0) { - short data; - data = *fp; - if (put_user(data, up++)) - return -EFAULT; - fp+=2; - count--; - } - } else { - if (copy_to_user((u_char *)userPtr, fp, count * 4)) - return -EFAULT; - } - *frameUsed += used * 4; - return stereo? used * 4: used * 2; -} - -static ssize_t cs4218_ct_u16_read(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - int mask = (sound.soft.format == AFMT_U16_LE? 0x0080: 0x8000); - int stereo = sound.soft.stereo; - short *fp = (short *) &frame[*frameUsed]; - short *up = (short *) userPtr; - - frameLeft >>= 2; - userCount >>= (stereo? 2: 1); - used = count = min(userCount, frameLeft); - while (count > 0) { - int data; - - data = *fp++; - data ^= mask; - if (put_user(data, up++)) - return -EFAULT; - if (stereo) { - data = *fp; - data ^= mask; - if (put_user(data, up++)) - return -EFAULT; - } - fp++; - count--; - } - *frameUsed += used * 4; - return stereo? used * 4: used * 2; -} - -static TRANS transCSNormal = { - cs4218_ct_law, cs4218_ct_law, cs4218_ct_s8, cs4218_ct_u8, - cs4218_ct_s16, cs4218_ct_u16, cs4218_ct_s16, cs4218_ct_u16 -}; - -static TRANS transCSExpand = { - cs4218_ctx_law, cs4218_ctx_law, cs4218_ctx_s8, cs4218_ctx_u8, - cs4218_ctx_s16, cs4218_ctx_u16, cs4218_ctx_s16, cs4218_ctx_u16 -}; - -static TRANS transCSNormalRead = { - NULL, NULL, cs4218_ct_s8_read, cs4218_ct_u8_read, - cs4218_ct_s16_read, cs4218_ct_u16_read, - cs4218_ct_s16_read, cs4218_ct_u16_read -}; - -/*** Low level stuff *********************************************************/ - -static void *CS_Alloc(unsigned int size, gfp_t flags) -{ - int order; - - size >>= 13; - for (order=0; order < 5; order++) { - if (size == 0) - break; - size >>= 1; - } - return (void *)__get_free_pages(flags, order); -} - -static void CS_Free(void *ptr, unsigned int size) -{ - int order; - - size >>= 13; - for (order=0; order < 5; order++) { - if (size == 0) - break; - size >>= 1; - } - free_pages((ulong)ptr, order); -} - -static int __init CS_IrqInit(void) -{ - cpm_install_handler(CPMVEC_SMC2, cs4218_intr, NULL); - return 1; -} - -#ifdef MODULE -static void CS_IrqCleanup(void) -{ - volatile smc_t *sp; - volatile cpm8xx_t *cp; - - /* First disable transmitter and receiver. - */ - sp = &cpmp->cp_smc[1]; - sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); - - /* And now shut down the SMC. - */ - cp = cpmp; /* Get pointer to Communication Processor */ - cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2, - CPM_CR_STOP_TX) | CPM_CR_FLG; - while (cp->cp_cpcr & CPM_CR_FLG); - - /* Release the interrupt handler. - */ - cpm_free_handler(CPMVEC_SMC2); - - kfree(beep_buf); - kd_mksound = orig_mksound; -} -#endif /* MODULE */ - -static void CS_Silence(void) -{ - volatile smc_t *sp; - - /* Disable transmitter. - */ - sp = &cpmp->cp_smc[1]; - sp->smc_smcmr &= ~SMCMR_TEN; -} - -/* Frequencies depend upon external oscillator. There are two - * choices, 12.288 and 11.2896 MHz. The RPCG audio supports both through - * and external control register selection bit. - */ -static int cs4218_freqs[] = { - /* 12.288 11.2896 */ - 48000, 44100, - 32000, 29400, - 24000, 22050, - 19200, 17640, - 16000, 14700, - 12000, 11025, - 9600, 8820, - 8000, 7350 -}; - -static void CS_Init(void) -{ - int i, tolerance; - - switch (sound.soft.format) { - case AFMT_S16_LE: - case AFMT_U16_LE: - sound.hard.format = AFMT_S16_LE; - break; - default: - sound.hard.format = AFMT_S16_BE; - break; - } - sound.hard.stereo = 1; - sound.hard.size = 16; - - /* - * If we have a sample rate which is within catchRadius percent - * of the requested value, we don't have to expand the samples. - * Otherwise choose the next higher rate. - */ - i = (sizeof(cs4218_freqs) / sizeof(int)); - do { - tolerance = catchRadius * cs4218_freqs[--i] / 100; - } while (sound.soft.speed > cs4218_freqs[i] + tolerance && i > 0); - if (sound.soft.speed >= cs4218_freqs[i] - tolerance) - sound.trans_write = &transCSNormal; - else - sound.trans_write = &transCSExpand; - sound.trans_read = &transCSNormalRead; - sound.hard.speed = cs4218_freqs[i]; - cs4218_rate_index = i; - - /* The CS4218 has seven selectable clock dividers for the sample - * clock. The HIOX then provides one of two external rates. - * An even numbered frequency table index uses the high external - * clock rate. - */ - *(uint *)HIOX_CSR4_ADDR &= ~(HIOX_CSR4_AUDCLKHI | HIOX_CSR4_AUDCLKSEL); - if ((i & 1) == 0) - *(uint *)HIOX_CSR4_ADDR |= HIOX_CSR4_AUDCLKHI; - i >>= 1; - *(uint *)HIOX_CSR4_ADDR |= (i & HIOX_CSR4_AUDCLKSEL); - - expand_bal = -sound.soft.speed; -} - -static int CS_SetFormat(int format) -{ - int size; - - switch (format) { - case AFMT_QUERY: - return sound.soft.format; - case AFMT_MU_LAW: - case AFMT_A_LAW: - case AFMT_U8: - case AFMT_S8: - size = 8; - break; - case AFMT_S16_BE: - case AFMT_U16_BE: - case AFMT_S16_LE: - case AFMT_U16_LE: - size = 16; - break; - default: /* :-) */ - printk(KERN_ERR "dmasound: unknown format 0x%x, using AFMT_U8\n", - format); - size = 8; - format = AFMT_U8; - } - - sound.soft.format = format; - sound.soft.size = size; - if (sound.minDev == SND_DEV_DSP) { - sound.dsp.format = format; - sound.dsp.size = size; - } - - CS_Init(); - - return format; -} - -/* Volume is the amount of attenuation we tell the codec to impose - * on the outputs. There are 32 levels, with 0 the "loudest". - */ -#define CS_VOLUME_TO_MASK(x) (31 - ((((x) - 1) * 31) / 99)) -#define CS_MASK_TO_VOLUME(y) (100 - ((y) * 99 / 31)) - -static int cs_get_volume(uint reg) -{ - int volume; - - volume = CS_MASK_TO_VOLUME(CS_LATTEN_GET(reg)); - volume |= CS_MASK_TO_VOLUME(CS_RATTEN_GET(reg)) << 8; - return volume; -} - -static int cs_volume_setter(int volume, int mute) -{ - uint tempctl; - - if (mute && volume == 0) { - tempctl = cs4218_control | CS_MUTE; - } else { - tempctl = cs4218_control & ~CS_MUTE; - tempctl = tempctl & ~(CS_LATTEN | CS_RATTEN); - tempctl |= CS_LATTEN_SET(CS_VOLUME_TO_MASK(volume & 0xff)); - tempctl |= CS_RATTEN_SET(CS_VOLUME_TO_MASK((volume >> 8) & 0xff)); - volume = cs_get_volume(tempctl); - } - if (tempctl != cs4218_control) { - cs4218_ctl_write(tempctl); - } - return volume; -} - - -/* Gain has 16 steps from 0 to 15. These are in 1.5dB increments from - * 0 (no gain) to 22.5 dB. - */ -#define CS_RECLEVEL_TO_GAIN(v) \ - ((v) < 0 ? 0 : (v) > 100 ? 15 : (v) * 3 / 20) -#define CS_GAIN_TO_RECLEVEL(v) (((v) * 20 + 2) / 3) - -static int cs_get_gain(uint reg) -{ - int gain; - - gain = CS_GAIN_TO_RECLEVEL(CS_LGAIN_GET(reg)); - gain |= CS_GAIN_TO_RECLEVEL(CS_RGAIN_GET(reg)) << 8; - return gain; -} - -static int cs_set_gain(int gain) -{ - uint tempctl; - - tempctl = cs4218_control & ~(CS_LGAIN | CS_RGAIN); - tempctl |= CS_LGAIN_SET(CS_RECLEVEL_TO_GAIN(gain & 0xff)); - tempctl |= CS_RGAIN_SET(CS_RECLEVEL_TO_GAIN((gain >> 8) & 0xff)); - gain = cs_get_gain(tempctl); - - if (tempctl != cs4218_control) { - cs4218_ctl_write(tempctl); - } - return gain; -} - -static int CS_SetVolume(int volume) -{ - return cs_volume_setter(volume, CS_MUTE); -} - -static void CS_Play(void) -{ - int i, count; - unsigned long flags; - volatile cbd_t *bdp; - volatile cpm8xx_t *cp; - - /* Protect buffer */ - spin_lock_irqsave(&cs4218_lock, flags); -#if 0 - if (awacs_beep_state) { - /* sound takes precedence over beeps */ - out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); - out_le32(&awacs->control, - (in_le32(&awacs->control) & ~0x1f00) - | (awacs_rate_index << 8)); - out_le32(&awacs->byteswap, sound.hard.format != AFMT_S16_BE); - out_le32(&awacs_txdma->cmdptr, virt_to_bus(&(awacs_tx_cmds[(sq.front+sq.active) % sq.max_count]))); - - beep_playing = 0; - awacs_beep_state = 0; - } -#endif - i = sq.front + sq.active; - if (i >= sq.max_count) - i -= sq.max_count; - while (sq.active < 2 && sq.active < sq.count) { - count = (sq.count == sq.active + 1)?sq.rear_size:sq.block_size; - if (count < sq.block_size && !sq.syncing) - /* last block not yet filled, and we're not syncing. */ - break; - - bdp = &tx_base[i]; - bdp->cbd_datlen = count; - - flush_dcache_range((ulong)sound_buffers[i], - (ulong)(sound_buffers[i] + count)); - - if (++i >= sq.max_count) - i = 0; - - if (sq.active == 0) { - /* The SMC does not load its fifo until the first - * TDM frame pulse, so the transmit data gets shifted - * by one word. To compensate for this, we incorrectly - * transmit the first buffer and shorten it by one - * word. Subsequent buffers are then aligned properly. - */ - bdp->cbd_datlen -= 2; - - /* Start up the SMC Transmitter. - */ - cp = cpmp; - cp->cp_smc[1].smc_smcmr |= SMCMR_TEN; - cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2, - CPM_CR_RESTART_TX) | CPM_CR_FLG; - while (cp->cp_cpcr & CPM_CR_FLG); - } - - /* Buffer is ready now. - */ - bdp->cbd_sc |= BD_SC_READY; - - ++sq.active; - } - spin_unlock_irqrestore(&cs4218_lock, flags); -} - - -static void CS_Record(void) -{ - unsigned long flags; - volatile smc_t *sp; - - if (read_sq.active) - return; - - /* Protect buffer */ - spin_lock_irqsave(&cs4218_lock, flags); - - /* This is all we have to do......Just start it up. - */ - sp = &cpmp->cp_smc[1]; - sp->smc_smcmr |= SMCMR_REN; - - read_sq.active = 1; - - spin_unlock_irqrestore(&cs4218_lock, flags); -} - - -static void -cs4218_tdm_tx_intr(void *devid) -{ - int i = sq.front; - volatile cbd_t *bdp; - - while (sq.active > 0) { - bdp = &tx_base[i]; - if (bdp->cbd_sc & BD_SC_READY) - break; /* this frame is still going */ - --sq.count; - --sq.active; - if (++i >= sq.max_count) - i = 0; - } - if (i != sq.front) - WAKE_UP(sq.action_queue); - sq.front = i; - - CS_Play(); - - if (!sq.active) - WAKE_UP(sq.sync_queue); -} - - -static void -cs4218_tdm_rx_intr(void *devid) -{ - - /* We want to blow 'em off when shutting down. - */ - if (read_sq.active == 0) - return; - - /* Check multiple buffers in case we were held off from - * interrupt processing for a long time. Geeze, I really hope - * this doesn't happen. - */ - while ((rx_base[read_sq.rear].cbd_sc & BD_SC_EMPTY) == 0) { - - /* Invalidate the data cache range for this buffer. - */ - invalidate_dcache_range( - (uint)(sound_read_buffers[read_sq.rear]), - (uint)(sound_read_buffers[read_sq.rear] + read_sq.block_size)); - - /* Make buffer available again and move on. - */ - rx_base[read_sq.rear].cbd_sc |= BD_SC_EMPTY; - read_sq.rear++; - - /* Wrap the buffer ring. - */ - if (read_sq.rear >= read_sq.max_active) - read_sq.rear = 0; - - /* If we have caught up to the front buffer, bump it. - * This will cause weird (but not fatal) results if the - * read loop is currently using this buffer. The user is - * behind in this case anyway, so weird things are going - * to happen. - */ - if (read_sq.rear == read_sq.front) { - read_sq.front++; - if (read_sq.front >= read_sq.max_active) - read_sq.front = 0; - } - } - - WAKE_UP(read_sq.action_queue); -} - -static void cs_nosound(unsigned long xx) -{ - unsigned long flags; - - /* not sure if this is needed, since hardware command is #if 0'd */ - spin_lock_irqsave(&cs4218_lock, flags); - if (beep_playing) { -#if 0 - st_le16(&beep_dbdma_cmd->command, DBDMA_STOP); -#endif - beep_playing = 0; - } - spin_unlock_irqrestore(&cs4218_lock, flags); -} - -static DEFINE_TIMER(beep_timer, cs_nosound, 0, 0); - -static void cs_mksound(unsigned int hz, unsigned int ticks) -{ - unsigned long flags; - int beep_speed = BEEP_SPEED; - int srate = cs4218_freqs[beep_speed]; - int period, ncycles, nsamples; - int i, j, f; - short *p; - static int beep_hz_cache; - static int beep_nsamples_cache; - static int beep_volume_cache; - - if (hz <= srate / BEEP_BUFLEN || hz > srate / 2) { -#if 1 - /* this is a hack for broken X server code */ - hz = 750; - ticks = 12; -#else - /* cancel beep currently playing */ - awacs_nosound(0); - return; -#endif - } - /* lock while modifying beep_timer */ - spin_lock_irqsave(&cs4218_lock, flags); - del_timer(&beep_timer); - if (ticks) { - beep_timer.expires = jiffies + ticks; - add_timer(&beep_timer); - } - if (beep_playing || sq.active || beep_buf == NULL) { - spin_unlock_irqrestore(&cs4218_lock, flags); - return; /* too hard, sorry :-( */ - } - beep_playing = 1; -#if 0 - st_le16(&beep_dbdma_cmd->command, OUTPUT_MORE + BR_ALWAYS); -#endif - spin_unlock_irqrestore(&cs4218_lock, flags); - - if (hz == beep_hz_cache && beep_volume == beep_volume_cache) { - nsamples = beep_nsamples_cache; - } else { - period = srate * 256 / hz; /* fixed point */ - ncycles = BEEP_BUFLEN * 256 / period; - nsamples = (period * ncycles) >> 8; - f = ncycles * 65536 / nsamples; - j = 0; - p = beep_buf; - for (i = 0; i < nsamples; ++i, p += 2) { - p[0] = p[1] = beep_wform[j >> 8] * beep_volume; - j = (j + f) & 0xffff; - } - beep_hz_cache = hz; - beep_volume_cache = beep_volume; - beep_nsamples_cache = nsamples; - } - -#if 0 - st_le16(&beep_dbdma_cmd->req_count, nsamples*4); - st_le16(&beep_dbdma_cmd->xfer_status, 0); - st_le32(&beep_dbdma_cmd->cmd_dep, virt_to_bus(beep_dbdma_cmd)); - st_le32(&beep_dbdma_cmd->phy_addr, virt_to_bus(beep_buf)); - awacs_beep_state = 1; - - spin_lock_irqsave(&cs4218_lock, flags); - if (beep_playing) { /* i.e. haven't been terminated already */ - out_le32(&awacs_txdma->control, (RUN|WAKE|FLUSH|PAUSE) << 16); - out_le32(&awacs->control, - (in_le32(&awacs->control) & ~0x1f00) - | (beep_speed << 8)); - out_le32(&awacs->byteswap, 0); - out_le32(&awacs_txdma->cmdptr, virt_to_bus(beep_dbdma_cmd)); - out_le32(&awacs_txdma->control, RUN | (RUN << 16)); - } - spin_unlock_irqrestore(&cs4218_lock, flags); -#endif -} - -static MACHINE mach_cs4218 = { - .owner = THIS_MODULE, - .name = "HIOX CS4218", - .name2 = "Built-in Sound", - .dma_alloc = CS_Alloc, - .dma_free = CS_Free, - .irqinit = CS_IrqInit, -#ifdef MODULE - .irqcleanup = CS_IrqCleanup, -#endif /* MODULE */ - .init = CS_Init, - .silence = CS_Silence, - .setFormat = CS_SetFormat, - .setVolume = CS_SetVolume, - .play = CS_Play -}; - - -/*** Mid level stuff *********************************************************/ - - -static void sound_silence(void) -{ - /* update hardware settings one more */ - (*sound.mach.init)(); - - (*sound.mach.silence)(); -} - - -static void sound_init(void) -{ - (*sound.mach.init)(); -} - - -static int sound_set_format(int format) -{ - return(*sound.mach.setFormat)(format); -} - - -static int sound_set_speed(int speed) -{ - if (speed < 0) - return(sound.soft.speed); - - sound.soft.speed = speed; - (*sound.mach.init)(); - if (sound.minDev == SND_DEV_DSP) - sound.dsp.speed = sound.soft.speed; - - return(sound.soft.speed); -} - - -static int sound_set_stereo(int stereo) -{ - if (stereo < 0) - return(sound.soft.stereo); - - stereo = !!stereo; /* should be 0 or 1 now */ - - sound.soft.stereo = stereo; - if (sound.minDev == SND_DEV_DSP) - sound.dsp.stereo = stereo; - (*sound.mach.init)(); - - return(stereo); -} - - -static int sound_set_volume(int volume) -{ - return(*sound.mach.setVolume)(volume); -} - -static ssize_t sound_copy_translate(const u_char *userPtr, - size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t (*ct_func)(const u_char *, size_t, u_char *, ssize_t *, ssize_t) = NULL; - - switch (sound.soft.format) { - case AFMT_MU_LAW: - ct_func = sound.trans_write->ct_ulaw; - break; - case AFMT_A_LAW: - ct_func = sound.trans_write->ct_alaw; - break; - case AFMT_S8: - ct_func = sound.trans_write->ct_s8; - break; - case AFMT_U8: - ct_func = sound.trans_write->ct_u8; - break; - case AFMT_S16_BE: - ct_func = sound.trans_write->ct_s16be; - break; - case AFMT_U16_BE: - ct_func = sound.trans_write->ct_u16be; - break; - case AFMT_S16_LE: - ct_func = sound.trans_write->ct_s16le; - break; - case AFMT_U16_LE: - ct_func = sound.trans_write->ct_u16le; - break; - } - if (ct_func) - return ct_func(userPtr, userCount, frame, frameUsed, frameLeft); - else - return 0; -} - -static ssize_t sound_copy_translate_read(const u_char *userPtr, - size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t (*ct_func)(const u_char *, size_t, u_char *, ssize_t *, ssize_t) = NULL; - - switch (sound.soft.format) { - case AFMT_MU_LAW: - ct_func = sound.trans_read->ct_ulaw; - break; - case AFMT_A_LAW: - ct_func = sound.trans_read->ct_alaw; - break; - case AFMT_S8: - ct_func = sound.trans_read->ct_s8; - break; - case AFMT_U8: - ct_func = sound.trans_read->ct_u8; - break; - case AFMT_S16_BE: - ct_func = sound.trans_read->ct_s16be; - break; - case AFMT_U16_BE: - ct_func = sound.trans_read->ct_u16be; - break; - case AFMT_S16_LE: - ct_func = sound.trans_read->ct_s16le; - break; - case AFMT_U16_LE: - ct_func = sound.trans_read->ct_u16le; - break; - } - if (ct_func) - return ct_func(userPtr, userCount, frame, frameUsed, frameLeft); - else - return 0; -} - - -/* - * /dev/mixer abstraction - */ - -static int mixer_open(struct inode *inode, struct file *file) -{ - mixer.busy = 1; - return nonseekable_open(inode, file); -} - - -static int mixer_release(struct inode *inode, struct file *file) -{ - mixer.busy = 0; - return 0; -} - - -static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg) -{ - int data; - uint tmpcs; - - if (_SIOC_DIR(cmd) & _SIOC_WRITE) - mixer.modify_counter++; - if (cmd == OSS_GETVERSION) - return IOCTL_OUT(arg, SOUND_VERSION); - switch (cmd) { - case SOUND_MIXER_INFO: { - mixer_info info; - strlcpy(info.id, "CS4218_TDM", sizeof(info.id)); - strlcpy(info.name, "CS4218_TDM", sizeof(info.name)); - info.name[sizeof(info.name)-1] = 0; - info.modify_counter = mixer.modify_counter; - if (copy_to_user((int *)arg, &info, sizeof(info))) - return -EFAULT; - return 0; - } - case SOUND_MIXER_READ_DEVMASK: - data = SOUND_MASK_VOLUME | SOUND_MASK_LINE - | SOUND_MASK_MIC | SOUND_MASK_RECLEV - | SOUND_MASK_ALTPCM; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_RECMASK: - data = SOUND_MASK_LINE | SOUND_MASK_MIC; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_RECSRC: - if (cs4218_control & CS_DO1) - data = SOUND_MASK_LINE; - else - data = SOUND_MASK_MIC; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_WRITE_RECSRC: - IOCTL_IN(arg, data); - data &= (SOUND_MASK_LINE | SOUND_MASK_MIC); - if (data & SOUND_MASK_LINE) - tmpcs = cs4218_control | - (CS_ISL | CS_ISR | CS_DO1); - if (data & SOUND_MASK_MIC) - tmpcs = cs4218_control & - ~(CS_ISL | CS_ISR | CS_DO1); - if (tmpcs != cs4218_control) - cs4218_ctl_write(tmpcs); - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_STEREODEVS: - data = SOUND_MASK_VOLUME | SOUND_MASK_RECLEV; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_CAPS: - return IOCTL_OUT(arg, 0); - case SOUND_MIXER_READ_VOLUME: - data = (cs4218_control & CS_MUTE)? 0: - cs_get_volume(cs4218_control); - return IOCTL_OUT(arg, data); - case SOUND_MIXER_WRITE_VOLUME: - IOCTL_IN(arg, data); - return IOCTL_OUT(arg, sound_set_volume(data)); - case SOUND_MIXER_WRITE_ALTPCM: /* really bell volume */ - IOCTL_IN(arg, data); - beep_volume = data & 0xff; - /* fall through */ - case SOUND_MIXER_READ_ALTPCM: - return IOCTL_OUT(arg, beep_volume); - case SOUND_MIXER_WRITE_RECLEV: - IOCTL_IN(arg, data); - data = cs_set_gain(data); - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_RECLEV: - data = cs_get_gain(cs4218_control); - return IOCTL_OUT(arg, data); - } - - return -EINVAL; -} - - -static const struct file_operations mixer_fops = -{ - .owner = THIS_MODULE, - .llseek = sound_lseek, - .ioctl = mixer_ioctl, - .open = mixer_open, - .release = mixer_release, -}; - - -static void __init mixer_init(void) -{ - mixer_unit = register_sound_mixer(&mixer_fops, -1); - if (mixer_unit < 0) - return; - - mixer.busy = 0; - sound.treble = 0; - sound.bass = 0; - - /* Set Line input, no gain, no attenuation. - */ - cs4218_control = CS_ISL | CS_ISR | CS_DO1; - cs4218_control |= CS_LGAIN_SET(0) | CS_RGAIN_SET(0); - cs4218_control |= CS_LATTEN_SET(0) | CS_RATTEN_SET(0); - cs4218_ctl_write(cs4218_control); -} - - -/* - * Sound queue stuff, the heart of the driver - */ - - -static int sq_allocate_buffers(void) -{ - int i; - - if (sound_buffers) - return 0; - sound_buffers = kmalloc (numBufs * sizeof(char *), GFP_KERNEL); - if (!sound_buffers) - return -ENOMEM; - for (i = 0; i < numBufs; i++) { - sound_buffers[i] = sound.mach.dma_alloc (bufSize << 10, GFP_KERNEL); - if (!sound_buffers[i]) { - while (i--) - sound.mach.dma_free (sound_buffers[i], bufSize << 10); - kfree (sound_buffers); - sound_buffers = 0; - return -ENOMEM; - } - } - return 0; -} - - -static void sq_release_buffers(void) -{ - int i; - - if (sound_buffers) { - for (i = 0; i < numBufs; i++) - sound.mach.dma_free (sound_buffers[i], bufSize << 10); - kfree (sound_buffers); - sound_buffers = 0; - } -} - - -static int sq_allocate_read_buffers(void) -{ - int i; - - if (sound_read_buffers) - return 0; - sound_read_buffers = kmalloc(numReadBufs * sizeof(char *), GFP_KERNEL); - if (!sound_read_buffers) - return -ENOMEM; - for (i = 0; i < numBufs; i++) { - sound_read_buffers[i] = sound.mach.dma_alloc (readbufSize<<10, - GFP_KERNEL); - if (!sound_read_buffers[i]) { - while (i--) - sound.mach.dma_free (sound_read_buffers[i], - readbufSize << 10); - kfree (sound_read_buffers); - sound_read_buffers = 0; - return -ENOMEM; - } - } - return 0; -} - -static void sq_release_read_buffers(void) -{ - int i; - - if (sound_read_buffers) { - cpmp->cp_smc[1].smc_smcmr &= ~SMCMR_REN; - for (i = 0; i < numReadBufs; i++) - sound.mach.dma_free (sound_read_buffers[i], - bufSize << 10); - kfree (sound_read_buffers); - sound_read_buffers = 0; - } -} - - -static void sq_setup(int numBufs, int bufSize, char **write_buffers) -{ - int i; - volatile cbd_t *bdp; - volatile cpm8xx_t *cp; - volatile smc_t *sp; - - /* Make sure the SMC transmit is shut down. - */ - cp = cpmp; - sp = &cpmp->cp_smc[1]; - sp->smc_smcmr &= ~SMCMR_TEN; - - sq.max_count = numBufs; - sq.max_active = numBufs; - sq.block_size = bufSize; - sq.buffers = write_buffers; - - sq.front = sq.count = 0; - sq.rear = -1; - sq.syncing = 0; - sq.active = 0; - - bdp = tx_base; - for (i=0; i<numBufs; i++) { - bdp->cbd_bufaddr = virt_to_bus(write_buffers[i]); - bdp++; - } - - /* This causes the SMC to sync up with the first buffer again. - */ - cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2, CPM_CR_INIT_TX) | CPM_CR_FLG; - while (cp->cp_cpcr & CPM_CR_FLG); -} - -static void read_sq_setup(int numBufs, int bufSize, char **read_buffers) -{ - int i; - volatile cbd_t *bdp; - volatile cpm8xx_t *cp; - volatile smc_t *sp; - - /* Make sure the SMC receive is shut down. - */ - cp = cpmp; - sp = &cpmp->cp_smc[1]; - sp->smc_smcmr &= ~SMCMR_REN; - - read_sq.max_count = numBufs; - read_sq.max_active = numBufs; - read_sq.block_size = bufSize; - read_sq.buffers = read_buffers; - - read_sq.front = read_sq.count = 0; - read_sq.rear = 0; - read_sq.rear_size = 0; - read_sq.syncing = 0; - read_sq.active = 0; - - bdp = rx_base; - for (i=0; i<numReadBufs; i++) { - bdp->cbd_bufaddr = virt_to_bus(read_buffers[i]); - bdp->cbd_datlen = read_sq.block_size; - bdp++; - } - - /* This causes the SMC to sync up with the first buffer again. - */ - cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2, CPM_CR_INIT_RX) | CPM_CR_FLG; - while (cp->cp_cpcr & CPM_CR_FLG); -} - - -static void sq_play(void) -{ - (*sound.mach.play)(); -} - - -/* ++TeSche: radically changed this one too */ - -static ssize_t sq_write(struct file *file, const char *src, size_t uLeft, - loff_t *ppos) -{ - ssize_t uWritten = 0; - u_char *dest; - ssize_t uUsed, bUsed, bLeft; - - /* ++TeSche: Is something like this necessary? - * Hey, that's an honest question! Or does any other part of the - * filesystem already checks this situation? I really don't know. - */ - if (uLeft == 0) - return 0; - - /* The interrupt doesn't start to play the last, incomplete frame. - * Thus we can append to it without disabling the interrupts! (Note - * also that sq.rear isn't affected by the interrupt.) - */ - - if (sq.count > 0 && (bLeft = sq.block_size-sq.rear_size) > 0) { - dest = sq_block_address(sq.rear); - bUsed = sq.rear_size; - uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft); - if (uUsed <= 0) - return uUsed; - src += uUsed; - uWritten += uUsed; - uLeft -= uUsed; - sq.rear_size = bUsed; - } - - do { - while (sq.count == sq.max_active) { - sq_play(); - if (NON_BLOCKING(sq.open_mode)) - return uWritten > 0 ? uWritten : -EAGAIN; - SLEEP(sq.action_queue); - if (SIGNAL_RECEIVED) - return uWritten > 0 ? uWritten : -EINTR; - } - - /* Here, we can avoid disabling the interrupt by first - * copying and translating the data, and then updating - * the sq variables. Until this is done, the interrupt - * won't see the new frame and we can work on it - * undisturbed. - */ - - dest = sq_block_address((sq.rear+1) % sq.max_count); - bUsed = 0; - bLeft = sq.block_size; - uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft); - if (uUsed <= 0) - break; - src += uUsed; - uWritten += uUsed; - uLeft -= uUsed; - if (bUsed) { - sq.rear = (sq.rear+1) % sq.max_count; - sq.rear_size = bUsed; - sq.count++; - } - } while (bUsed); /* uUsed may have been 0 */ - - sq_play(); - - return uUsed < 0? uUsed: uWritten; -} - - -/***********/ - -/* Here is how the values are used for reading. - * The value 'active' simply indicates the DMA is running. This is - * done so the driver semantics are DMA starts when the first read is - * posted. The value 'front' indicates the buffer we should next - * send to the user. The value 'rear' indicates the buffer the DMA is - * currently filling. When 'front' == 'rear' the buffer "ring" is - * empty (we always have an empty available). The 'rear_size' is used - * to track partial offsets into the current buffer. Right now, I just keep - * The DMA running. If the reader can't keep up, the interrupt tosses - * the oldest buffer. We could also shut down the DMA in this case. - */ -static ssize_t sq_read(struct file *file, char *dst, size_t uLeft, - loff_t *ppos) -{ - - ssize_t uRead, bLeft, bUsed, uUsed; - - if (uLeft == 0) - return 0; - - if (!read_sq.active) - CS_Record(); /* Kick off the record process. */ - - uRead = 0; - - /* Move what the user requests, depending upon other options. - */ - while (uLeft > 0) { - - /* When front == rear, the DMA is not done yet. - */ - while (read_sq.front == read_sq.rear) { - if (NON_BLOCKING(read_sq.open_mode)) { - return uRead > 0 ? uRead : -EAGAIN; - } - SLEEP(read_sq.action_queue); - if (SIGNAL_RECEIVED) - return uRead > 0 ? uRead : -EINTR; - } - - /* The amount we move is either what is left in the - * current buffer or what the user wants. - */ - bLeft = read_sq.block_size - read_sq.rear_size; - bUsed = read_sq.rear_size; - uUsed = sound_copy_translate_read(dst, uLeft, - read_sq.buffers[read_sq.front], &bUsed, bLeft); - if (uUsed <= 0) - return uUsed; - dst += uUsed; - uRead += uUsed; - uLeft -= uUsed; - read_sq.rear_size += bUsed; - if (read_sq.rear_size >= read_sq.block_size) { - read_sq.rear_size = 0; - read_sq.front++; - if (read_sq.front >= read_sq.max_active) - read_sq.front = 0; - } - } - return uRead; -} - -static int sq_open(struct inode *inode, struct file *file) -{ - int rc = 0; - - if (file->f_mode & FMODE_WRITE) { - if (sq.busy) { - rc = -EBUSY; - if (NON_BLOCKING(file->f_flags)) - goto err_out; - rc = -EINTR; - while (sq.busy) { - SLEEP(sq.open_queue); - if (SIGNAL_RECEIVED) - goto err_out; - } - } - sq.busy = 1; /* Let's play spot-the-race-condition */ - - if (sq_allocate_buffers()) goto err_out_nobusy; - - sq_setup(numBufs, bufSize<<10,sound_buffers); - sq.open_mode = file->f_mode; - } - - - if (file->f_mode & FMODE_READ) { - if (read_sq.busy) { - rc = -EBUSY; - if (NON_BLOCKING(file->f_flags)) - goto err_out; - rc = -EINTR; - while (read_sq.busy) { - SLEEP(read_sq.open_queue); - if (SIGNAL_RECEIVED) - goto err_out; - } - rc = 0; - } - read_sq.busy = 1; - if (sq_allocate_read_buffers()) goto err_out_nobusy; - - read_sq_setup(numReadBufs,readbufSize<<10, sound_read_buffers); - read_sq.open_mode = file->f_mode; - } - - /* Start up the 4218 by: - * Reset. - * Enable, unreset. - */ - *((volatile uint *)HIOX_CSR4_ADDR) &= ~HIOX_CSR4_RSTAUDIO; - eieio(); - *((volatile uint *)HIOX_CSR4_ADDR) |= HIOX_CSR4_ENAUDIO; - mdelay(50); - *((volatile uint *)HIOX_CSR4_ADDR) |= HIOX_CSR4_RSTAUDIO; - - /* We need to send the current control word in case someone - * opened /dev/mixer and changed things while we were shut - * down. Chances are good the initialization that follows - * would have done this, but it is still possible it wouldn't. - */ - cs4218_ctl_write(cs4218_control); - - sound.minDev = iminor(inode) & 0x0f; - sound.soft = sound.dsp; - sound.hard = sound.dsp; - sound_init(); - if ((iminor(inode) & 0x0f) == SND_DEV_AUDIO) { - sound_set_speed(8000); - sound_set_stereo(0); - sound_set_format(AFMT_MU_LAW); - } - - return nonseekable_open(inode, file); - -err_out_nobusy: - if (file->f_mode & FMODE_WRITE) { - sq.busy = 0; - WAKE_UP(sq.open_queue); - } - if (file->f_mode & FMODE_READ) { - read_sq.busy = 0; - WAKE_UP(read_sq.open_queue); - } -err_out: - return rc; -} - - -static void sq_reset(void) -{ - sound_silence(); - sq.active = 0; - sq.count = 0; - sq.front = (sq.rear+1) % sq.max_count; -#if 0 - init_tdm_buffers(); -#endif -} - - -static int sq_fsync(struct file *filp, struct dentry *dentry) -{ - int rc = 0; - - sq.syncing = 1; - sq_play(); /* there may be an incomplete frame waiting */ - - while (sq.active) { - SLEEP(sq.sync_queue); - if (SIGNAL_RECEIVED) { - /* While waiting for audio output to drain, an - * interrupt occurred. Stop audio output immediately - * and clear the queue. */ - sq_reset(); - rc = -EINTR; - break; - } - } - - sq.syncing = 0; - return rc; -} - -static int sq_release(struct inode *inode, struct file *file) -{ - int rc = 0; - - if (sq.busy) - rc = sq_fsync(file, file->f_path.dentry); - sound.soft = sound.dsp; - sound.hard = sound.dsp; - sound_silence(); - - sq_release_read_buffers(); - sq_release_buffers(); - - if (file->f_mode & FMODE_READ) { - read_sq.busy = 0; - WAKE_UP(read_sq.open_queue); - } - - if (file->f_mode & FMODE_WRITE) { - sq.busy = 0; - WAKE_UP(sq.open_queue); - } - - /* Shut down the SMC. - */ - cpmp->cp_smc[1].smc_smcmr &= ~(SMCMR_TEN | SMCMR_REN); - - /* Shut down the codec. - */ - *((volatile uint *)HIOX_CSR4_ADDR) |= HIOX_CSR4_RSTAUDIO; - eieio(); - *((volatile uint *)HIOX_CSR4_ADDR) &= ~HIOX_CSR4_ENAUDIO; - - /* Wake up a process waiting for the queue being released. - * Note: There may be several processes waiting for a call - * to open() returning. */ - - return rc; -} - - -static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg) -{ - u_long fmt; - int data; -#if 0 - int size, nbufs; -#else - int size; -#endif - - switch (cmd) { - case SNDCTL_DSP_RESET: - sq_reset(); - return 0; - case SNDCTL_DSP_POST: - case SNDCTL_DSP_SYNC: - return sq_fsync(file, file->f_path.dentry); - - /* ++TeSche: before changing any of these it's - * probably wise to wait until sound playing has - * settled down. */ - case SNDCTL_DSP_SPEED: - sq_fsync(file, file->f_path.dentry); - IOCTL_IN(arg, data); - return IOCTL_OUT(arg, sound_set_speed(data)); - case SNDCTL_DSP_STEREO: - sq_fsync(file, file->f_path.dentry); - IOCTL_IN(arg, data); - return IOCTL_OUT(arg, sound_set_stereo(data)); - case SOUND_PCM_WRITE_CHANNELS: - sq_fsync(file, file->f_path.dentry); - IOCTL_IN(arg, data); - return IOCTL_OUT(arg, sound_set_stereo(data-1)+1); - case SNDCTL_DSP_SETFMT: - sq_fsync(file, file->f_path.dentry); - IOCTL_IN(arg, data); - return IOCTL_OUT(arg, sound_set_format(data)); - case SNDCTL_DSP_GETFMTS: - fmt = 0; - if (sound.trans_write) { - if (sound.trans_write->ct_ulaw) - fmt |= AFMT_MU_LAW; - if (sound.trans_write->ct_alaw) - fmt |= AFMT_A_LAW; - if (sound.trans_write->ct_s8) - fmt |= AFMT_S8; - if (sound.trans_write->ct_u8) - fmt |= AFMT_U8; - if (sound.trans_write->ct_s16be) - fmt |= AFMT_S16_BE; - if (sound.trans_write->ct_u16be) - fmt |= AFMT_U16_BE; - if (sound.trans_write->ct_s16le) - fmt |= AFMT_S16_LE; - if (sound.trans_write->ct_u16le) - fmt |= AFMT_U16_LE; - } - return IOCTL_OUT(arg, fmt); - case SNDCTL_DSP_GETBLKSIZE: - size = sq.block_size - * sound.soft.size * (sound.soft.stereo + 1) - / (sound.hard.size * (sound.hard.stereo + 1)); - return IOCTL_OUT(arg, size); - case SNDCTL_DSP_SUBDIVIDE: - break; -#if 0 /* Sorry can't do this at the moment. The CPM allocated buffers - * long ago that can't be changed. - */ - case SNDCTL_DSP_SETFRAGMENT: - if (sq.count || sq.active || sq.syncing) - return -EINVAL; - IOCTL_IN(arg, size); - nbufs = size >> 16; - if (nbufs < 2 || nbufs > numBufs) - nbufs = numBufs; - size &= 0xffff; - if (size >= 8 && size <= 30) { - size = 1 << size; - size *= sound.hard.size * (sound.hard.stereo + 1); - size /= sound.soft.size * (sound.soft.stereo + 1); - if (size > (bufSize << 10)) - size = bufSize << 10; - } else - size = bufSize << 10; - sq_setup(numBufs, size, sound_buffers); - sq.max_active = nbufs; - return 0; -#endif - - default: - return mixer_ioctl(inode, file, cmd, arg); - } - return -EINVAL; -} - - - -static const struct file_operations sq_fops = -{ - .owner = THIS_MODULE, - .llseek = sound_lseek, - .read = sq_read, /* sq_read */ - .write = sq_write, - .ioctl = sq_ioctl, - .open = sq_open, - .release = sq_release, -}; - - -static void __init sq_init(void) -{ - sq_unit = register_sound_dsp(&sq_fops, -1); - if (sq_unit < 0) - return; - - init_waitqueue_head(&sq.action_queue); - init_waitqueue_head(&sq.open_queue); - init_waitqueue_head(&sq.sync_queue); - init_waitqueue_head(&read_sq.action_queue); - init_waitqueue_head(&read_sq.open_queue); - init_waitqueue_head(&read_sq.sync_queue); - - sq.busy = 0; - read_sq.busy = 0; - - /* whatever you like as startup mode for /dev/dsp, - * (/dev/audio hasn't got a startup mode). note that - * once changed a new open() will *not* restore these! - */ - sound.dsp.format = AFMT_S16_BE; - sound.dsp.stereo = 1; - sound.dsp.size = 16; - - /* set minimum rate possible without expanding */ - sound.dsp.speed = 8000; - - /* before the first open to /dev/dsp this wouldn't be set */ - sound.soft = sound.dsp; - sound.hard = sound.dsp; - - sound_silence(); -} - -/* - * /dev/sndstat - */ - - -/* state.buf should not overflow! */ - -static int state_open(struct inode *inode, struct file *file) -{ - char *buffer = state.buf, *mach = "", cs4218_buf[50]; - int len = 0; - - if (state.busy) - return -EBUSY; - - state.ptr = 0; - state.busy = 1; - - sprintf(cs4218_buf, "Crystal CS4218 on TDM, "); - mach = cs4218_buf; - - len += sprintf(buffer+len, "%sDMA sound driver:\n", mach); - - len += sprintf(buffer+len, "\tsound.format = 0x%x", sound.soft.format); - switch (sound.soft.format) { - case AFMT_MU_LAW: - len += sprintf(buffer+len, " (mu-law)"); - break; - case AFMT_A_LAW: - len += sprintf(buffer+len, " (A-law)"); - break; - case AFMT_U8: - len += sprintf(buffer+len, " (unsigned 8 bit)"); - break; - case AFMT_S8: - len += sprintf(buffer+len, " (signed 8 bit)"); - break; - case AFMT_S16_BE: - len += sprintf(buffer+len, " (signed 16 bit big)"); - break; - case AFMT_U16_BE: - len += sprintf(buffer+len, " (unsigned 16 bit big)"); - break; - case AFMT_S16_LE: - len += sprintf(buffer+len, " (signed 16 bit little)"); - break; - case AFMT_U16_LE: - len += sprintf(buffer+len, " (unsigned 16 bit little)"); - break; - } - len += sprintf(buffer+len, "\n"); - len += sprintf(buffer+len, "\tsound.speed = %dHz (phys. %dHz)\n", - sound.soft.speed, sound.hard.speed); - len += sprintf(buffer+len, "\tsound.stereo = 0x%x (%s)\n", - sound.soft.stereo, sound.soft.stereo ? "stereo" : "mono"); - len += sprintf(buffer+len, "\tsq.block_size = %d sq.max_count = %d" - " sq.max_active = %d\n", - sq.block_size, sq.max_count, sq.max_active); - len += sprintf(buffer+len, "\tsq.count = %d sq.rear_size = %d\n", sq.count, - sq.rear_size); - len += sprintf(buffer+len, "\tsq.active = %d sq.syncing = %d\n", - sq.active, sq.syncing); - state.len = len; - return nonseekable_open(inode, file); -} - - -static int state_release(struct inode *inode, struct file *file) -{ - state.busy = 0; - return 0; -} - - -static ssize_t state_read(struct file *file, char *buf, size_t count, - loff_t *ppos) -{ - int n = state.len - state.ptr; - if (n > count) - n = count; - if (n <= 0) - return 0; - if (copy_to_user(buf, &state.buf[state.ptr], n)) - return -EFAULT; - state.ptr += n; - return n; -} - - -static const struct file_operations state_fops = -{ - .owner = THIS_MODULE, - .llseek = sound_lseek, - .read = state_read, - .open = state_open, - .release = state_release, -}; - - -static void __init state_init(void) -{ - state_unit = register_sound_special(&state_fops, SND_DEV_STATUS); - if (state_unit < 0) - return; - state.busy = 0; -} - - -/*** Common stuff ********************************************************/ - -static long long sound_lseek(struct file *file, long long offset, int orig) -{ - return -ESPIPE; -} - - -/*** Config & Setup **********************************************************/ - - -int __init tdm8xx_sound_init(void) -{ - int i, has_sound; - uint dp_offset; - volatile uint *sirp; - volatile cbd_t *bdp; - volatile cpm8xx_t *cp; - volatile smc_t *sp; - volatile smc_uart_t *up; - volatile immap_t *immap; - - has_sound = 0; - - /* Program the SI/TSA to use TDMa, connected to SMC2, for 4 bytes. - */ - cp = cpmp; /* Get pointer to Communication Processor */ - immap = (immap_t *)IMAP_ADDR; /* and to internal registers */ - - /* Set all TDMa control bits to zero. This enables most features - * we want. - */ - cp->cp_simode &= ~0x00000fff; - - /* Enable common receive/transmit clock pins, use IDL format. - * Sync on falling edge, transmit rising clock, receive falling - * clock, delay 1 bit on both Tx and Rx. Common Tx/Rx clocks and - * sync. - * Connect SMC2 to TSA. - */ - cp->cp_simode |= 0x80000141; - - /* Configure port A pins for TDMa operation. - * The RPX-Lite (MPC850/823) loses SMC2 when TDM is used. - */ - immap->im_ioport.iop_papar |= 0x01c0; /* Enable TDMa functions */ - immap->im_ioport.iop_padir |= 0x00c0; /* Enable TDMa Tx/Rx */ - immap->im_ioport.iop_padir &= ~0x0100; /* Enable L1RCLKa */ - - immap->im_ioport.iop_pcpar |= 0x0800; /* Enable L1RSYNCa */ - immap->im_ioport.iop_pcdir &= ~0x0800; - - /* Initialize the SI TDM routing table. We use TDMa only. - * The receive table and transmit table each have only one - * entry, to capture/send four bytes after each frame pulse. - * The 16-bit ram entry is 0000 0001 1000 1111. (SMC2) - */ - cp->cp_sigmr = 0; - sirp = (uint *)cp->cp_siram; - - *sirp = 0x018f0000; /* Receive entry */ - sirp += 64; - *sirp = 0x018f0000; /* Tramsmit entry */ - - /* Enable single TDMa routing. - */ - cp->cp_sigmr = 0x04; - - /* Initialize the SMC for transparent operation. - */ - sp = &cpmp->cp_smc[1]; - up = (smc_uart_t *)&cp->cp_dparam[PROFF_SMC2]; - - /* We need to allocate a transmit and receive buffer - * descriptors from dual port ram. - */ - dp_addr = cpm_dpalloc(sizeof(cbd_t) * numReadBufs, 8); - - /* Set the physical address of the host memory - * buffers in the buffer descriptors, and the - * virtual address for us to work with. - */ - bdp = (cbd_t *)&cp->cp_dpmem[dp_addr]; - up->smc_rbase = dp_offset; - rx_cur = rx_base = (cbd_t *)bdp; - - for (i=0; i<(numReadBufs-1); i++) { - bdp->cbd_bufaddr = 0; - bdp->cbd_datlen = 0; - bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT; - bdp++; - } - bdp->cbd_bufaddr = 0; - bdp->cbd_datlen = 0; - bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT; - - /* Now, do the same for the transmit buffers. - */ - dp_offset = cpm_dpalloc(sizeof(cbd_t) * numBufs, 8); - - bdp = (cbd_t *)&cp->cp_dpmem[dp_addr]; - up->smc_tbase = dp_offset; - tx_cur = tx_base = (cbd_t *)bdp; - - for (i=0; i<(numBufs-1); i++) { - bdp->cbd_bufaddr = 0; - bdp->cbd_datlen = 0; - bdp->cbd_sc = BD_SC_INTRPT; - bdp++; - } - bdp->cbd_bufaddr = 0; - bdp->cbd_datlen = 0; - bdp->cbd_sc = (BD_SC_WRAP | BD_SC_INTRPT); - - /* Set transparent SMC mode. - * A few things are specific to our application. The codec interface - * is MSB first, hence the REVD selection. The CD/CTS pulse are - * used by the TSA to indicate the frame start to the SMC. - */ - up->smc_rfcr = SCC_EB; - up->smc_tfcr = SCC_EB; - up->smc_mrblr = readbufSize * 1024; - - /* Set 16-bit reversed data, transparent mode. - */ - sp->smc_smcmr = smcr_mk_clen(15) | - SMCMR_SM_TRANS | SMCMR_REVD | SMCMR_BS; - - /* Enable and clear events. - * Because of FIFO delays, all we need is the receive interrupt - * and we can process both the current receive and current - * transmit interrupt within a few microseconds of the transmit. - */ - sp->smc_smce = 0xff; - sp->smc_smcm = SMCM_TXE | SMCM_TX | SMCM_RX; - - /* Send the CPM an initialize command. - */ - cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2, - CPM_CR_INIT_TRX) | CPM_CR_FLG; - while (cp->cp_cpcr & CPM_CR_FLG); - - sound.mach = mach_cs4218; - has_sound = 1; - - /* Initialize beep stuff */ - orig_mksound = kd_mksound; - kd_mksound = cs_mksound; - beep_buf = kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL); - if (beep_buf == NULL) - printk(KERN_WARNING "dmasound: no memory for " - "beep buffer\n"); - - if (!has_sound) - return -ENODEV; - - /* Initialize the software SPI. - */ - sw_spi_init(); - - /* Set up sound queue, /dev/audio and /dev/dsp. */ - - /* Set default settings. */ - sq_init(); - - /* Set up /dev/sndstat. */ - state_init(); - - /* Set up /dev/mixer. */ - mixer_init(); - - if (!sound.mach.irqinit()) { - printk(KERN_ERR "DMA sound driver: Interrupt initialization failed\n"); - return -ENODEV; - } -#ifdef MODULE - irq_installed = 1; -#endif - - printk(KERN_INFO "DMA sound driver installed, using %d buffers of %dk.\n", - numBufs, bufSize); - - return 0; -} - -/* Due to FIFOs and bit delays, the transmit interrupt occurs a few - * microseconds ahead of the receive interrupt. - * When we get an interrupt, we service the transmit first, then - * check for a receive to prevent the overhead of returning through - * the interrupt handler only to get back here right away during - * full duplex operation. - */ -static void -cs4218_intr(void *dev_id) -{ - volatile smc_t *sp; - volatile cpm8xx_t *cp; - - sp = &cpmp->cp_smc[1]; - - if (sp->smc_smce & SCCM_TX) { - sp->smc_smce = SCCM_TX; - cs4218_tdm_tx_intr((void *)sp); - } - - if (sp->smc_smce & SCCM_RX) { - sp->smc_smce = SCCM_RX; - cs4218_tdm_rx_intr((void *)sp); - } - - if (sp->smc_smce & SCCM_TXE) { - /* Transmit underrun. This happens with the application - * didn't keep up sending buffers. We tell the SMC to - * restart, which will cause it to poll the current (next) - * BD. If the user supplied data since this occurred, - * we just start running again. If they didn't, the SMC - * will poll the descriptor until data is placed there. - */ - sp->smc_smce = SCCM_TXE; - cp = cpmp; /* Get pointer to Communication Processor */ - cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2, - CPM_CR_RESTART_TX) | CPM_CR_FLG; - while (cp->cp_cpcr & CPM_CR_FLG); - } -} - - -#define MAXARGS 8 /* Should be sufficient for now */ - -void __init dmasound_setup(char *str, int *ints) -{ - /* check the bootstrap parameter for "dmasound=" */ - - switch (ints[0]) { - case 3: - if ((ints[3] < 0) || (ints[3] > MAX_CATCH_RADIUS)) - printk("dmasound_setup: invalid catch radius, using default = %d\n", catchRadius); - else - catchRadius = ints[3]; - /* fall through */ - case 2: - if (ints[1] < MIN_BUFFERS) - printk("dmasound_setup: invalid number of buffers, using default = %d\n", numBufs); - else - numBufs = ints[1]; - if (ints[2] < MIN_BUFSIZE || ints[2] > MAX_BUFSIZE) - printk("dmasound_setup: invalid buffer size, using default = %d\n", bufSize); - else - bufSize = ints[2]; - break; - case 0: - break; - default: - printk("dmasound_setup: invalid number of arguments\n"); - } -} - -/* Software SPI functions. - * These are on Port B. - */ -#define PB_SPICLK ((uint)0x00000002) -#define PB_SPIMOSI ((uint)0x00000004) -#define PB_SPIMISO ((uint)0x00000008) - -static -void sw_spi_init(void) -{ - volatile cpm8xx_t *cp; - volatile uint *hcsr4; - - hcsr4 = (volatile uint *)HIOX_CSR4_ADDR; - cp = cpmp; /* Get pointer to Communication Processor */ - - *hcsr4 &= ~HIOX_CSR4_AUDSPISEL; /* Disable SPI select */ - - /* Make these Port B signals general purpose I/O. - * First, make sure the clock is low. - */ - cp->cp_pbdat &= ~PB_SPICLK; - cp->cp_pbpar &= ~(PB_SPICLK | PB_SPIMOSI | PB_SPIMISO); - - /* Clock and Master Output are outputs. - */ - cp->cp_pbdir |= (PB_SPICLK | PB_SPIMOSI); - - /* Master Input. - */ - cp->cp_pbdir &= ~PB_SPIMISO; - -} - -/* Write the CS4218 control word out the SPI port. While the - * the control word is going out, the status word is arriving. - */ -static -uint cs4218_ctl_write(uint ctlreg) -{ - uint status; - - sw_spi_io((u_char *)&ctlreg, (u_char *)&status, 4); - - /* Shadow the control register.....I guess we could do - * the same for the status, but for now we just return it - * and let the caller decide. - */ - cs4218_control = ctlreg; - return status; -} - -static -void sw_spi_io(u_char *obuf, u_char *ibuf, uint bcnt) -{ - int bits, i; - u_char outbyte, inbyte; - volatile cpm8xx_t *cp; - volatile uint *hcsr4; - - hcsr4 = (volatile uint *)HIOX_CSR4_ADDR; - cp = cpmp; /* Get pointer to Communication Processor */ - - /* The timing on the bus is pretty slow. Code inefficiency - * and eieio() is our friend here :-). - */ - cp->cp_pbdat &= ~PB_SPICLK; - *hcsr4 |= HIOX_CSR4_AUDSPISEL; /* Enable SPI select */ - eieio(); - - /* Clock in/out the bytes. Data is valid on the falling edge - * of the clock. Data is MSB first. - */ - for (i=0; i<bcnt; i++) { - outbyte = *obuf++; - inbyte = 0; - for (bits=0; bits<8; bits++) { - eieio(); - cp->cp_pbdat |= PB_SPICLK; - eieio(); - if (outbyte & 0x80) - cp->cp_pbdat |= PB_SPIMOSI; - else - cp->cp_pbdat &= ~PB_SPIMOSI; - eieio(); - cp->cp_pbdat &= ~PB_SPICLK; - eieio(); - outbyte <<= 1; - inbyte <<= 1; - if (cp->cp_pbdat & PB_SPIMISO) - inbyte |= 1; - } - *ibuf++ = inbyte; - } - - *hcsr4 &= ~HIOX_CSR4_AUDSPISEL; /* Disable SPI select */ - eieio(); -} - -void cleanup_module(void) -{ - if (irq_installed) { - sound_silence(); -#ifdef MODULE - sound.mach.irqcleanup(); -#endif - } - - sq_release_read_buffers(); - sq_release_buffers(); - - if (mixer_unit >= 0) - unregister_sound_mixer(mixer_unit); - if (state_unit >= 0) - unregister_sound_special(state_unit); - if (sq_unit >= 0) - unregister_sound_dsp(sq_unit); -} - -module_init(tdm8xx_sound_init); -module_exit(cleanup_module); - diff --git a/arch/ppc/boot/common/misc-common.c b/arch/ppc/boot/common/misc-common.c index 8e1fccd..9589969 100644 --- a/arch/ppc/boot/common/misc-common.c +++ b/arch/ppc/boot/common/misc-common.c @@ -57,7 +57,8 @@ unsigned char *ISA_io = NULL; #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \ || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \ - || defined(CONFIG_SERIAL_MPSC_CONSOLE) + || defined(CONFIG_SERIAL_MPSC_CONSOLE) \ + || defined(CONFIG_SERIAL_UARTLITE_CONSOLE) extern unsigned long com_port; extern int serial_tstc(unsigned long com_port); @@ -80,7 +81,8 @@ int tstc(void) { #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \ || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \ - || defined(CONFIG_SERIAL_MPSC_CONSOLE) + || defined(CONFIG_SERIAL_MPSC_CONSOLE) \ + || defined(CONFIG_SERIAL_UARTLITE_CONSOLE) if(keyb_present) return (CRT_tstc() || serial_tstc(com_port)); else @@ -95,7 +97,8 @@ int getc(void) while (1) { #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \ || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \ - || defined(CONFIG_SERIAL_MPSC_CONSOLE) + || defined(CONFIG_SERIAL_MPSC_CONSOLE) \ + || defined(CONFIG_SERIAL_UARTLITE_CONSOLE) if (serial_tstc(com_port)) return (serial_getc(com_port)); #endif /* serial console */ @@ -112,7 +115,8 @@ putc(const char c) #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \ || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \ - || defined(CONFIG_SERIAL_MPSC_CONSOLE) + || defined(CONFIG_SERIAL_MPSC_CONSOLE) \ + || defined(CONFIG_SERIAL_UARTLITE_CONSOLE) serial_putc(com_port, c); if ( c == '\n' ) serial_putc(com_port, '\r'); @@ -161,7 +165,8 @@ void puts(const char *s) while ( ( c = *s++ ) != '\0' ) { #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \ || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \ - || defined(CONFIG_SERIAL_MPSC_CONSOLE) + || defined(CONFIG_SERIAL_MPSC_CONSOLE) \ + || defined(CONFIG_SERIAL_UARTLITE_CONSOLE) serial_putc(com_port, c); if ( c == '\n' ) serial_putc(com_port, '\r'); #endif /* serial console */ diff --git a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile index bcfb6cd..5b87779 100644 --- a/arch/ppc/boot/simple/Makefile +++ b/arch/ppc/boot/simple/Makefile @@ -201,6 +201,7 @@ boot-$(CONFIG_8260) += m8260_tty.o endif boot-$(CONFIG_SERIAL_MPC52xx_CONSOLE) += mpc52xx_tty.o boot-$(CONFIG_SERIAL_MPSC_CONSOLE) += mv64x60_tty.o +boot-$(CONFIG_SERIAL_UARTLITE_CONSOLE) += uartlite_tty.o LIBS := $(common)/lib.a $(bootlib)/lib.a ifeq ($(CONFIG_PPC_PREP),y) diff --git a/arch/ppc/boot/simple/uartlite_tty.c b/arch/ppc/boot/simple/uartlite_tty.c new file mode 100644 index 0000000..0eae1ea --- /dev/null +++ b/arch/ppc/boot/simple/uartlite_tty.c @@ -0,0 +1,37 @@ +/* + * Xilinx UARTLITE bootloader driver + * + * Copyright (c) 2007 Secret Lab Technologies Ltd. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/types.h> +#include <asm/serial.h> +#include <asm/io.h> +#include <platforms/4xx/xparameters/xparameters.h> + +#define UARTLITE_BASEADDR ((void*)(XPAR_UARTLITE_0_BASEADDR)) + +void +serial_putc(unsigned long com_port, unsigned char c) +{ + while ((in_be32(UARTLITE_BASEADDR + 0x8) & 0x08) != 0); /* spin */ + out_be32(UARTLITE_BASEADDR + 0x4, c); +} + +unsigned char +serial_getc(unsigned long com_port) +{ + while ((in_be32(UARTLITE_BASEADDR + 0x8) & 0x01) == 0); /* spin */ + return in_be32(UARTLITE_BASEADDR); +} + +int +serial_tstc(unsigned long com_port) +{ + return ((in_be32(UARTLITE_BASEADDR + 0x8) & 0x01) != 0); +} diff --git a/arch/ppc/kernel/asm-offsets.c b/arch/ppc/kernel/asm-offsets.c index 1f91eca..c5850a2 100644 --- a/arch/ppc/kernel/asm-offsets.c +++ b/arch/ppc/kernel/asm-offsets.c @@ -40,7 +40,6 @@ main(void) DEFINE(PTRACE, offsetof(struct task_struct, ptrace)); DEFINE(KSP, offsetof(struct thread_struct, ksp)); DEFINE(PGDIR, offsetof(struct thread_struct, pgdir)); - DEFINE(LAST_SYSCALL, offsetof(struct thread_struct, last_syscall)); DEFINE(PT_REGS, offsetof(struct thread_struct, regs)); DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode)); DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0])); diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S index a9d4553..ab64256 100644 --- a/arch/ppc/kernel/entry.S +++ b/arch/ppc/kernel/entry.S @@ -191,7 +191,6 @@ stack_ovf: 0: _GLOBAL(DoSyscall) - stw r0,THREAD+LAST_SYSCALL(r2) stw r3,ORIG_GPR3(r1) li r12,0 stw r12,RESULT(r1) diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig index 705ae56..76551b6 100644 --- a/arch/ppc/platforms/4xx/Kconfig +++ b/arch/ppc/platforms/4xx/Kconfig @@ -29,6 +29,7 @@ config CPCI405 config EP405 bool "EP405/EP405PC" + select EMBEDDEDBOOT help This option enables support for the EP405/EP405PC boards. @@ -54,11 +55,15 @@ config WALNUT config XILINX_ML300 bool "Xilinx-ML300" + select XILINX_VIRTEX_II_PRO + select EMBEDDEDBOOT help This option enables support for the Xilinx ML300 evaluation board. config XILINX_ML403 bool "Xilinx-ML403" + select XILINX_VIRTEX_4_FX + select EMBEDDEDBOOT help This option enables support for the Xilinx ML403 evaluation board. endchoice @@ -215,18 +220,14 @@ config 405GPR config XILINX_VIRTEX_II_PRO bool - depends on XILINX_ML300 - default y + select XILINX_VIRTEX config XILINX_VIRTEX_4_FX bool - depends on XILINX_ML403 - default y + select XILINX_VIRTEX config XILINX_VIRTEX bool - depends on XILINX_VIRTEX_II_PRO || XILINX_VIRTEX_4_FX - default y config STB03xxx bool @@ -235,8 +236,6 @@ config STB03xxx config EMBEDDEDBOOT bool - depends on EP405 || XILINX_ML300 || XILINX_ML403 - default y config IBM_OPENBIOS bool diff --git a/arch/ppc/platforms/4xx/Makefile b/arch/ppc/platforms/4xx/Makefile index fa6610b..723ad79 100644 --- a/arch/ppc/platforms/4xx/Makefile +++ b/arch/ppc/platforms/4xx/Makefile @@ -28,5 +28,4 @@ obj-$(CONFIG_440SP) += ibm440sp.o obj-$(CONFIG_440SPE) += ppc440spe.o obj-$(CONFIG_405EP) += ibm405ep.o obj-$(CONFIG_405GPR) += ibm405gpr.o -obj-$(CONFIG_XILINX_VIRTEX) += virtex.o diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c index 84e999d..5e994e1 100644 --- a/arch/ppc/platforms/4xx/ocotea.c +++ b/arch/ppc/platforms/4xx/ocotea.c @@ -178,7 +178,7 @@ ocotea_setup_pcix(void) /* Setup 2GB PCI->PLB inbound memory window at 0, enable MSIs */ PCIX_WRITEL(0x00000000, PCIX0_PIM0LAH); PCIX_WRITEL(0x00000000, PCIX0_PIM0LAL); - PCIX_WRITEL(0xe0000007, PCIX0_PIM0SA); + PCIX_WRITEL(0x80000007, PCIX0_PIM0SA); eieio(); } @@ -289,7 +289,7 @@ ocotea_setup_arch(void) * from FPGA, because it can be changed by on-board switches * --ebs */ - ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200); + ibm440gx_get_clocks(&clocks, 33300000, 6 * 1843200); ocp_sys_info.opb_bus_freq = clocks.opb; /* Setup TODC access */ diff --git a/arch/ppc/platforms/4xx/taishan.c b/arch/ppc/platforms/4xx/taishan.c index bb0253e..5d9af8d 100644 --- a/arch/ppc/platforms/4xx/taishan.c +++ b/arch/ppc/platforms/4xx/taishan.c @@ -235,7 +235,7 @@ taishan_setup_pcix(void) /* Setup 2GB PCI->PLB inbound memory window at 0, enable MSIs */ PCIX_WRITEL(0x00000000, PCIX0_PIM0LAH); PCIX_WRITEL(0x00000000, PCIX0_PIM0LAL); - PCIX_WRITEL(0xe0000007, PCIX0_PIM0SA); + PCIX_WRITEL(0x80000007, PCIX0_PIM0SA); PCIX_WRITEL(0xffffffff, PCIX0_PIM0SAH); iounmap(pcix_reg_base); diff --git a/arch/ppc/platforms/4xx/virtex.c b/arch/ppc/platforms/4xx/virtex.c deleted file mode 100644 index 133a831..0000000 --- a/arch/ppc/platforms/4xx/virtex.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Virtex-II Pro & Virtex-4 FX common infrastructure - * - * Maintainer: Grant Likely <grant.likely@secretlab.ca> - * - * Copyright 2005 Secret Lab Technologies Ltd. - * Copyright 2005 General Dynamics Canada Ltd. - * Copyright 2005 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. - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/device.h> -#include <linux/serial_8250.h> -#include <asm/ppc_sys.h> -#include <platforms/4xx/virtex.h> -#include <platforms/4xx/xparameters/xparameters.h> - -#define XPAR_UART(num) { \ - .mapbase = XPAR_UARTNS550_##num##_BASEADDR + 3, \ - .irq = XPAR_INTC_0_UARTNS550_##num##_VEC_ID, \ - .iotype = UPIO_MEM, \ - .uartclk = XPAR_UARTNS550_##num##_CLOCK_FREQ_HZ, \ - .flags = UPF_BOOT_AUTOCONF, \ - .regshift = 2, \ - } - -struct plat_serial8250_port serial_platform_data[] = { -#ifdef XPAR_UARTNS550_0_BASEADDR - XPAR_UART(0), -#endif -#ifdef XPAR_UARTNS550_1_BASEADDR - XPAR_UART(1), -#endif -#ifdef XPAR_UARTNS550_2_BASEADDR - XPAR_UART(2), -#endif -#ifdef XPAR_UARTNS550_3_BASEADDR - XPAR_UART(3), -#endif - { }, /* terminated by empty record */ -}; - -struct platform_device ppc_sys_platform_devices[] = { - [VIRTEX_UART] = { - .name = "serial8250", - .id = 0, - .dev.platform_data = serial_platform_data, - }, -}; - diff --git a/arch/ppc/platforms/4xx/virtex.h b/arch/ppc/platforms/4xx/virtex.h index c14325d..7382804 100644 --- a/arch/ppc/platforms/4xx/virtex.h +++ b/arch/ppc/platforms/4xx/virtex.h @@ -1,35 +1,35 @@ /* - * arch/ppc/platforms/4xx/virtex.h + * Basic Virtex platform defines, included by <asm/ibm4xx.h> * - * Include file that defines the Xilinx Virtex-II Pro processor + * 2005-2007 (c) Secret Lab Technologies Ltd. + * 2002-2004 (c) MontaVista Software, Inc. * - * Author: MontaVista Software, Inc. - * source@mvista.com - * - * 2002-2004 (c) MontaVista Software, Inc. This file is licensed under the - * terms of the GNU General Public License version 2. This program is licensed - * "as is" without any warranty of any kind, whether express or implied. + * 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. */ #ifdef __KERNEL__ #ifndef __ASM_VIRTEX_H__ #define __ASM_VIRTEX_H__ -/* serial defines */ - #include <asm/ibm405.h> +#include <asm/ppcboot.h> /* Ugly, ugly, ugly! BASE_BAUD defined here to keep 8250.c happy. */ #if !defined(BASE_BAUD) #define BASE_BAUD (0) /* dummy value; not used */ #endif - -/* Device type enumeration for platform bus definitions */ + #ifndef __ASSEMBLY__ -enum ppc_sys_devices { - VIRTEX_UART, NUM_PPC_SYS_DEVS, -}; -#endif - +extern const char* virtex_machine_name; +#define PPC4xx_MACHINE_NAME (virtex_machine_name) +#endif /* !__ASSEMBLY__ */ + +/* We don't need anything mapped. Size of zero will accomplish that. */ +#define PPC4xx_ONB_IO_PADDR 0u +#define PPC4xx_ONB_IO_VADDR 0u +#define PPC4xx_ONB_IO_SIZE 0u + #endif /* __ASM_VIRTEX_H__ */ #endif /* __KERNEL__ */ diff --git a/arch/ppc/platforms/4xx/xilinx_ml300.c b/arch/ppc/platforms/4xx/xilinx_ml300.c index fb5f0b5..6e522fe 100644 --- a/arch/ppc/platforms/4xx/xilinx_ml300.c +++ b/arch/ppc/platforms/4xx/xilinx_ml300.c @@ -18,9 +18,9 @@ #include <linux/serialP.h> #include <asm/io.h> #include <asm/machdep.h> -#include <asm/ppc_sys.h> #include <syslib/gen550.h> +#include <syslib/virtex_devices.h> #include <platforms/4xx/xparameters/xparameters.h> /* @@ -53,24 +53,9 @@ * ppc4xx_pic_init arch/ppc/syslib/xilinx_pic.c */ -/* Board specifications structures */ -struct ppc_sys_spec *cur_ppc_sys_spec; -struct ppc_sys_spec ppc_sys_specs[] = { - { - /* Only one entry, always assume the same design */ - .ppc_sys_name = "Xilinx ML300 Reference Design", - .mask = 0x00000000, - .value = 0x00000000, - .num_devices = 1, - .device_list = (enum ppc_sys_devices[]) - { - VIRTEX_UART, - }, - }, -}; +const char* virtex_machine_name = "ML300 Reference Design"; #if defined(XPAR_POWER_0_POWERDOWN_BASEADDR) - static volatile unsigned *powerdown_base = (volatile unsigned *) XPAR_POWER_0_POWERDOWN_BASEADDR; @@ -95,52 +80,14 @@ ml300_map_io(void) #endif } -/* Early serial support functions */ -static void __init -ml300_early_serial_init(int num, struct plat_serial8250_port *pdata) -{ -#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) - struct uart_port serial_req; - - memset(&serial_req, 0, sizeof(serial_req)); - serial_req.mapbase = pdata->mapbase; - serial_req.membase = pdata->membase; - serial_req.irq = pdata->irq; - serial_req.uartclk = pdata->uartclk; - serial_req.regshift = pdata->regshift; - serial_req.iotype = pdata->iotype; - serial_req.flags = pdata->flags; - gen550_init(num, &serial_req); -#endif -} - -void __init -ml300_early_serial_map(void) -{ -#ifdef CONFIG_SERIAL_8250 - struct plat_serial8250_port *pdata; - int i = 0; - - pdata = (struct plat_serial8250_port *) ppc_sys_get_pdata(VIRTEX_UART); - while(pdata && pdata->flags) - { - pdata->membase = ioremap(pdata->mapbase, 0x100); - ml300_early_serial_init(i, pdata); - pdata++; - i++; - } -#endif /* CONFIG_SERIAL_8250 */ -} - void __init ml300_setup_arch(void) { - ml300_early_serial_map(); + virtex_early_serial_map(); ppc4xx_setup_arch(); /* calls ppc4xx_find_bridges() */ /* Identify the system */ - printk(KERN_INFO "Xilinx Virtex-II Pro port\n"); - printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n"); + printk(KERN_INFO "Xilinx ML300 Reference System (Virtex-II Pro)\n"); } /* Called after board_setup_irq from ppc4xx_init_IRQ(). */ @@ -156,8 +103,6 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, { ppc4xx_init(r3, r4, r5, r6, r7); - identify_ppc_sys_by_id(mfspr(SPRN_PVR)); - ppc_md.setup_arch = ml300_setup_arch; ppc_md.setup_io_mappings = ml300_map_io; ppc_md.init_IRQ = ml300_init_irq; @@ -167,7 +112,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, #endif #ifdef CONFIG_KGDB - ppc_md.early_serial_map = ml300_early_serial_map; + ppc_md.early_serial_map = virtex_early_serial_map; #endif } diff --git a/arch/ppc/platforms/4xx/xilinx_ml300.h b/arch/ppc/platforms/4xx/xilinx_ml300.h deleted file mode 100644 index 3d57332..0000000 --- a/arch/ppc/platforms/4xx/xilinx_ml300.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Include file that defines the Xilinx ML300 evaluation board - * - * Author: MontaVista Software, Inc. - * source@mvista.com - * - * 2002-2004 (c) MontaVista Software, Inc. This file is licensed under the - * terms of the GNU General Public License version 2. This program is licensed - * "as is" without any warranty of any kind, whether express or implied. - */ - -#ifdef __KERNEL__ -#ifndef __ASM_XILINX_ML300_H__ -#define __ASM_XILINX_ML300_H__ - -/* ML300 has a Xilinx Virtex-II Pro processor */ -#include <platforms/4xx/virtex.h> - -#ifndef __ASSEMBLY__ - -#include <linux/types.h> - -typedef struct board_info { - unsigned int bi_memsize; /* DRAM installed, in bytes */ - unsigned char bi_enetaddr[6]; /* Local Ethernet MAC address */ - unsigned int bi_intfreq; /* Processor speed, in Hz */ - unsigned int bi_busfreq; /* PLB Bus speed, in Hz */ - unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */ -} bd_t; - -/* Some 4xx parts use a different timebase frequency from the internal clock. -*/ -#define bi_tbfreq bi_intfreq - -#endif /* !__ASSEMBLY__ */ - -/* We don't need anything mapped. Size of zero will accomplish that. */ -#define PPC4xx_ONB_IO_PADDR 0u -#define PPC4xx_ONB_IO_VADDR 0u -#define PPC4xx_ONB_IO_SIZE 0u - -#define PPC4xx_MACHINE_NAME "Xilinx ML300 Reference System" - -#endif /* __ASM_XILINX_ML300_H__ */ -#endif /* __KERNEL__ */ diff --git a/arch/ppc/platforms/4xx/xilinx_ml403.c b/arch/ppc/platforms/4xx/xilinx_ml403.c index cb3bf7a..bc3ace3 100644 --- a/arch/ppc/platforms/4xx/xilinx_ml403.c +++ b/arch/ppc/platforms/4xx/xilinx_ml403.c @@ -1,11 +1,9 @@ /* - * arch/ppc/platforms/4xx/xilinx_ml403.c - * * Xilinx ML403 evaluation board initialization * * Author: Grant Likely <grant.likely@secretlab.ca> * - * 2005 (c) Secret Lab Technologies Ltd. + * 2005-2007 (c) Secret Lab Technologies Ltd. * 2002-2004 (c) MontaVista Software, Inc. * * This file is licensed under the terms of the GNU General Public License @@ -22,9 +20,9 @@ #include <linux/serialP.h> #include <asm/io.h> #include <asm/machdep.h> -#include <asm/ppc_sys.h> #include <syslib/gen550.h> +#include <syslib/virtex_devices.h> #include <platforms/4xx/xparameters/xparameters.h> /* @@ -57,24 +55,9 @@ * ppc4xx_pic_init arch/ppc/syslib/xilinx_pic.c */ -/* Board specifications structures */ -struct ppc_sys_spec *cur_ppc_sys_spec; -struct ppc_sys_spec ppc_sys_specs[] = { - { - /* Only one entry, always assume the same design */ - .ppc_sys_name = "Xilinx ML403 Reference Design", - .mask = 0x00000000, - .value = 0x00000000, - .num_devices = 1, - .device_list = (enum ppc_sys_devices[]) - { - VIRTEX_UART, - }, - }, -}; +const char* virtex_machine_name = "ML403 Reference Design"; #if defined(XPAR_POWER_0_POWERDOWN_BASEADDR) - static volatile unsigned *powerdown_base = (volatile unsigned *) XPAR_POWER_0_POWERDOWN_BASEADDR; @@ -99,47 +82,10 @@ ml403_map_io(void) #endif } -/* Early serial support functions */ -static void __init -ml403_early_serial_init(int num, struct plat_serial8250_port *pdata) -{ -#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) - struct uart_port serial_req; - - memset(&serial_req, 0, sizeof(serial_req)); - serial_req.mapbase = pdata->mapbase; - serial_req.membase = pdata->membase; - serial_req.irq = pdata->irq; - serial_req.uartclk = pdata->uartclk; - serial_req.regshift = pdata->regshift; - serial_req.iotype = pdata->iotype; - serial_req.flags = pdata->flags; - gen550_init(num, &serial_req); -#endif -} - -void __init -ml403_early_serial_map(void) -{ -#ifdef CONFIG_SERIAL_8250 - struct plat_serial8250_port *pdata; - int i = 0; - - pdata = (struct plat_serial8250_port *) ppc_sys_get_pdata(VIRTEX_UART); - while(pdata && pdata->flags) - { - pdata->membase = ioremap(pdata->mapbase, 0x100); - ml403_early_serial_init(i, pdata); - pdata++; - i++; - } -#endif /* CONFIG_SERIAL_8250 */ -} - void __init ml403_setup_arch(void) { - ml403_early_serial_map(); + virtex_early_serial_map(); ppc4xx_setup_arch(); /* calls ppc4xx_find_bridges() */ /* Identify the system */ @@ -159,8 +105,6 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, { ppc4xx_init(r3, r4, r5, r6, r7); - identify_ppc_sys_by_id(mfspr(SPRN_PVR)); - ppc_md.setup_arch = ml403_setup_arch; ppc_md.setup_io_mappings = ml403_map_io; ppc_md.init_IRQ = ml403_init_irq; @@ -170,7 +114,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, #endif #ifdef CONFIG_KGDB - ppc_md.early_serial_map = ml403_early_serial_map; + ppc_md.early_serial_map = virtex_early_serial_map; #endif } diff --git a/arch/ppc/platforms/4xx/xilinx_ml403.h b/arch/ppc/platforms/4xx/xilinx_ml403.h deleted file mode 100644 index 4735969..0000000 --- a/arch/ppc/platforms/4xx/xilinx_ml403.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * arch/ppc/platforms/4xx/xilinx_ml403.h - * - * Include file that defines the Xilinx ML403 reference design - * - * Author: Grant Likely <grant.likely@secretlab.ca> - * - * 2005 (c) Secret Lab Technologies Ltd. - * 2002-2004 (c) MontaVista Software, Inc. - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - */ - -#ifdef __KERNEL__ -#ifndef __ASM_XILINX_ML403_H__ -#define __ASM_XILINX_ML403_H__ - -/* ML403 has a Xilinx Virtex-4 FPGA with a PPC405 hard core */ -#include <platforms/4xx/virtex.h> - -#ifndef __ASSEMBLY__ - -#include <linux/types.h> - -typedef struct board_info { - unsigned int bi_memsize; /* DRAM installed, in bytes */ - unsigned char bi_enetaddr[6]; /* Local Ethernet MAC address */ - unsigned int bi_intfreq; /* Processor speed, in Hz */ - unsigned int bi_busfreq; /* PLB Bus speed, in Hz */ - unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */ -} bd_t; - -/* Some 4xx parts use a different timebase frequency from the internal clock. -*/ -#define bi_tbfreq bi_intfreq - -#endif /* !__ASSEMBLY__ */ - -/* We don't need anything mapped. Size of zero will accomplish that. */ -#define PPC4xx_ONB_IO_PADDR 0u -#define PPC4xx_ONB_IO_VADDR 0u -#define PPC4xx_ONB_IO_SIZE 0u - -#define PPC4xx_MACHINE_NAME "Xilinx ML403 Reference Design" - -#endif /* __ASM_XILINX_ML403_H__ */ -#endif /* __KERNEL__ */ diff --git a/arch/ppc/platforms/4xx/xparameters/xparameters.h b/arch/ppc/platforms/4xx/xparameters/xparameters.h index 66ec5f3..01aa043 100644 --- a/arch/ppc/platforms/4xx/xparameters/xparameters.h +++ b/arch/ppc/platforms/4xx/xparameters/xparameters.h @@ -34,3 +34,63 @@ .io_type = SERIAL_IO_MEM, \ }, #endif + +/* + * A few reasonable defaults for the #defines which could be missing depending + * on the IP version or variant (e.g. OPB vs PLB) + */ + +#ifndef XPAR_EMAC_0_CAM_EXIST +#define XPAR_EMAC_0_CAM_EXIST 0 +#endif +#ifndef XPAR_EMAC_0_JUMBO_EXIST +#define XPAR_EMAC_0_JUMBO_EXIST 0 +#endif +#ifndef XPAR_EMAC_0_TX_DRE_TYPE +#define XPAR_EMAC_0_TX_DRE_TYPE 0 +#endif +#ifndef XPAR_EMAC_0_RX_DRE_TYPE +#define XPAR_EMAC_0_RX_DRE_TYPE 0 +#endif +#ifndef XPAR_EMAC_0_TX_INCLUDE_CSUM +#define XPAR_EMAC_0_TX_INCLUDE_CSUM 0 +#endif +#ifndef XPAR_EMAC_0_RX_INCLUDE_CSUM +#define XPAR_EMAC_0_RX_INCLUDE_CSUM 0 +#endif + +#ifndef XPAR_EMAC_1_CAM_EXIST +#define XPAR_EMAC_1_CAM_EXIST 0 +#endif +#ifndef XPAR_EMAC_1_JUMBO_EXIST +#define XPAR_EMAC_1_JUMBO_EXIST 0 +#endif +#ifndef XPAR_EMAC_1_TX_DRE_TYPE +#define XPAR_EMAC_1_TX_DRE_TYPE 0 +#endif +#ifndef XPAR_EMAC_1_RX_DRE_TYPE +#define XPAR_EMAC_1_RX_DRE_TYPE 0 +#endif +#ifndef XPAR_EMAC_1_TX_INCLUDE_CSUM +#define XPAR_EMAC_1_TX_INCLUDE_CSUM 0 +#endif +#ifndef XPAR_EMAC_1_RX_INCLUDE_CSUM +#define XPAR_EMAC_1_RX_INCLUDE_CSUM 0 +#endif + +#ifndef XPAR_GPIO_0_IS_DUAL +#define XPAR_GPIO_0_IS_DUAL 0 +#endif +#ifndef XPAR_GPIO_1_IS_DUAL +#define XPAR_GPIO_1_IS_DUAL 0 +#endif +#ifndef XPAR_GPIO_2_IS_DUAL +#define XPAR_GPIO_2_IS_DUAL 0 +#endif +#ifndef XPAR_GPIO_3_IS_DUAL +#define XPAR_GPIO_3_IS_DUAL 0 +#endif +#ifndef XPAR_GPIO_4_IS_DUAL +#define XPAR_GPIO_4_IS_DUAL 0 +#endif + diff --git a/arch/ppc/platforms/rpxclassic.h b/arch/ppc/platforms/rpxclassic.h index 57a2a55..a3c1118 100644 --- a/arch/ppc/platforms/rpxclassic.h +++ b/arch/ppc/platforms/rpxclassic.h @@ -69,10 +69,6 @@ extern bd_t m8xx_board_info; #define BCSR2_QSPACESEL ((uint)0x00004000) #define BCSR2_FETHLEDMODE ((uint)0x00000800) /* CLLF */ -#if defined(CONFIG_HTDMSOUND) -#include <platforms/rpxhiox.h> -#endif - /* define IO_BASE for pcmcia, CLLF only */ #if !defined(CONFIG_PCI) #define _IO_BASE 0x80000000 diff --git a/arch/ppc/platforms/rpxhiox.h b/arch/ppc/platforms/rpxhiox.h deleted file mode 100644 index c3fa5a6..0000000 --- a/arch/ppc/platforms/rpxhiox.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * The Embedded Planet HIOX expansion card definitions. - * There were a few different versions of these cards, but only - * the one that escaped real production is defined here. - * - * Copyright (c) 2000 Dan Malek (dmalek@jlc.net) - */ -#ifndef __MACH_RPX_HIOX_DEFS -#define __MACH_RPX_HIOX_DEFS - -#define HIOX_CSR_ADDR ((uint)0xfac00000) -#define HIOX_CSR_SIZE ((uint)(4 * 1024)) -#define HIOX_CSR0_ADDR HIOX_CSR_ADDR -#define HIOX_CSR4_ADDR ((uint)0xfac00004) - -#define HIOX_CSR0_DEFAULT ((uint)0x380f3c00) -#define HIOX_CSR0_ENSCC2 ((uint)0x80000000) -#define HIOX_CSR0_ENSMC2 ((uint)0x04000000) -#define HIOX_CSR0_ENVDOCLK ((uint)0x02000000) -#define HIOX_CSR0_VDORST_HL ((uint)0x01000000) -#define HIOX_CSR0_RS232SEL ((uint)0x0000c000) -#define HIOX_CSR0_SCC3SEL ((uint)0x0000c000) -#define HIOX_CSR0_SMC1SEL ((uint)0x00008000) -#define HIOX_CSR0_SCC1SEL ((uint)0x00004000) -#define HIOX_CSR0_ENTOUCH ((uint)0x00000080) -#define HIOX_CSR0_PDOWN100 ((uint)0x00000060) -#define HIOX_CSR0_PDOWN10 ((uint)0x00000040) -#define HIOX_CSR0_PDOWN1 ((uint)0x00000020) -#define HIOX_CSR0_TSELSPI ((uint)0x00000010) -#define HIOX_CSR0_TIRQSTAT ((uint)0x00000008) -#define HIOX_CSR4_DEFAULT ((uint)0x00000000) -#define HIOX_CSR4_ENTIRQ2 ((uint)0x20000000) -#define HIOX_CSR4_ENTIRQ3 ((uint)0x10000000) -#define HIOX_CSR4_ENAUDIO ((uint)0x00000080) -#define HIOX_CSR4_RSTAUDIO ((uint)0x00000040) /* 0 == reset */ -#define HIOX_CSR4_AUDCLKHI ((uint)0x00000020) -#define HIOX_CSR4_AUDSPISEL ((uint)0x00000010) -#define HIOX_CSR4_AUDIRQSTAT ((uint)0x00000008) -#define HIOX_CSR4_AUDCLKSEL ((uint)0x00000007) - -#endif diff --git a/arch/ppc/platforms/rpxlite.h b/arch/ppc/platforms/rpxlite.h index 7197806..b615501 100644 --- a/arch/ppc/platforms/rpxlite.h +++ b/arch/ppc/platforms/rpxlite.h @@ -57,10 +57,6 @@ extern bd_t m8xx_board_info; #define BCSR1_PCVCTL6 ((uint)0x00020000) #define BCSR1_PCVCTL7 ((uint)0x00010000) -#if defined(CONFIG_HTDMSOUND) -#include <platforms/rpxhiox.h> -#endif - /* define IO_BASE for pcmcia */ #define _IO_BASE 0x80000000 #define _IO_BASE_SIZE 0x1000 diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile index 0991111..95694159 100644 --- a/arch/ppc/syslib/Makefile +++ b/arch/ppc/syslib/Makefile @@ -18,7 +18,8 @@ obj-$(CONFIG_440SP) += ibm440gx_common.o ibm440sp_common.o obj-$(CONFIG_440SPE) += ibm440gx_common.o ibm440sp_common.o ppc440spe_pcie.o ifeq ($(CONFIG_4xx),y) ifeq ($(CONFIG_XILINX_VIRTEX),y) -obj-$(CONFIG_40x) += xilinx_pic.o ppc_sys.o +obj-$(CONFIG_40x) += xilinx_pic.o +obj-y += virtex_devices.o else ifeq ($(CONFIG_403),y) obj-$(CONFIG_40x) += ppc403_pic.o diff --git a/arch/ppc/syslib/cpc710.h b/arch/ppc/syslib/cpc710.h deleted file mode 100644 index 5299bf8..0000000 --- a/arch/ppc/syslib/cpc710.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Definitions for the IBM CPC710 PCI Host Bridge - * - * Author: Matt Porter <mporter@mvista.com> - * - * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#ifndef __PPC_PLATFORMS_CPC710_H -#define __PPC_PLATFORMS_CPC710_H - -/* General bridge and memory controller registers */ -#define PIDR 0xff000008 -#define CNFR 0xff00000c -#define RSTR 0xff000010 -#define UCTL 0xff001000 -#define MPSR 0xff001010 -#define SIOC 0xff001020 -#define ABCNTL 0xff001030 -#define SRST 0xff001040 -#define ERRC 0xff001050 -#define SESR 0xff001060 -#define SEAR 0xff001070 -#define SIOC1 0xff001090 -#define PGCHP 0xff001100 -#define GPDIR 0xff001130 -#define GPOUT 0xff001150 -#define ATAS 0xff001160 -#define AVDG 0xff001170 -#define MCCR 0xff001200 -#define MESR 0xff001220 -#define MEAR 0xff001230 -#define MCER0 0xff001300 -#define MCER1 0xff001310 -#define MCER2 0xff001320 -#define MCER3 0xff001330 -#define MCER4 0xff001340 -#define MCER5 0xff001350 -#define MCER6 0xff001360 -#define MCER7 0xff001370 - -/* - * PCI32/64 configuration registers - * Given as offsets from their - * respective physical segment BAR - */ -#define PIBAR 0x000f7800 -#define PMBAR 0x000f7810 -#define MSIZE 0x000f7f40 -#define IOSIZE 0x000f7f60 -#define SMBAR 0x000f7f80 -#define SIBAR 0x000f7fc0 -#define PSSIZE 0x000f8100 -#define PPSIZE 0x000f8110 -#define BARPS 0x000f8120 -#define BARPP 0x000f8130 -#define PSBAR 0x000f8140 -#define PPBAR 0x000f8150 -#define BPMDLK 0x000f8200 /* Bottom of Peripheral Memory Space */ -#define TPMDLK 0x000f8210 /* Top of Peripheral Memory Space */ -#define BIODLK 0x000f8220 /* Bottom of Peripheral I/O Space */ -#define TIODLK 0x000f8230 /* Top of Perioheral I/O Space */ -#define DLKCTRL 0x000f8240 /* Deadlock control */ -#define DLKDEV 0x000f8250 /* Deadlock device */ - -/* System standard configuration registers space */ -#define DCR 0xff200000 -#define DID 0xff200004 -#define BAR 0xff200018 - -/* Device specific configuration space */ -#define PCIENB 0xff201000 - -/* Configuration space registers */ -#define CPC710_BUS_NUMBER 0x40 -#define CPC710_SUB_BUS_NUMBER 0x41 - -#endif /* __PPC_PLATFORMS_CPC710_H */ diff --git a/arch/ppc/syslib/m8xx_setup.c b/arch/ppc/syslib/m8xx_setup.c index 01e48d8..9caf850 100644 --- a/arch/ppc/syslib/m8xx_setup.c +++ b/arch/ppc/syslib/m8xx_setup.c @@ -413,7 +413,7 @@ m8xx_map_io(void) io_block_mapping(_IO_BASE,_IO_BASE,_IO_BASE_SIZE, _PAGE_IO); #endif #endif -#if defined(CONFIG_HTDMSOUND) || defined(CONFIG_RPXTOUCH) || defined(CONFIG_FB_RPX) +#if defined(CONFIG_RPXTOUCH) || defined(CONFIG_FB_RPX) io_block_mapping(HIOX_CSR_ADDR, HIOX_CSR_ADDR, HIOX_CSR_SIZE, _PAGE_IO); #endif #ifdef CONFIG_FADS diff --git a/arch/ppc/syslib/ppc4xx_sgdma.c b/arch/ppc/syslib/ppc4xx_sgdma.c index 2f83e16..939abe3 100644 --- a/arch/ppc/syslib/ppc4xx_sgdma.c +++ b/arch/ppc/syslib/ppc4xx_sgdma.c @@ -27,6 +27,7 @@ #include <asm/system.h> #include <asm/io.h> +#include <asm/dma-mapping.h> #include <asm/ppc4xx_dma.h> void diff --git a/arch/ppc/syslib/virtex_devices.c b/arch/ppc/syslib/virtex_devices.c new file mode 100644 index 0000000..1654678 --- /dev/null +++ b/arch/ppc/syslib/virtex_devices.c @@ -0,0 +1,233 @@ +/* + * Virtex hard ppc405 core common device listing + * + * Copyright 2005-2007 Secret Lab Technologies Ltd. + * Copyright 2005 Freescale Semiconductor Inc. + * Copyright 2002-2004 MontaVista Software, 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. + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/device.h> +#include <linux/serial_8250.h> +#include <syslib/virtex_devices.h> +#include <platforms/4xx/xparameters/xparameters.h> +#include <asm/io.h> + +/* + * UARTLITE: shortcut macro for single instance + */ +#define XPAR_UARTLITE(num) { \ + .name = "uartlite", \ + .id = num, \ + .num_resources = 2, \ + .resource = (struct resource[]) { \ + { \ + .start = XPAR_UARTLITE_##num##_BASEADDR + 3, \ + .end = XPAR_UARTLITE_##num##_HIGHADDR, \ + .flags = IORESOURCE_MEM, \ + }, \ + { \ + .start = XPAR_INTC_0_UARTLITE_##num##_VEC_ID, \ + .flags = IORESOURCE_IRQ, \ + }, \ + }, \ +} + +/* + * Full UART: shortcut macro for single instance + platform data structure + */ +#define XPAR_UART(num) { \ + .mapbase = XPAR_UARTNS550_##num##_BASEADDR + 3, \ + .irq = XPAR_INTC_0_UARTNS550_##num##_VEC_ID, \ + .iotype = UPIO_MEM, \ + .uartclk = XPAR_UARTNS550_##num##_CLOCK_FREQ_HZ, \ + .flags = UPF_BOOT_AUTOCONF, \ + .regshift = 2, \ +} + +/* + * SystemACE: shortcut macro for single instance + */ +#define XPAR_SYSACE(num) { \ + .name = "xsysace", \ + .id = XPAR_SYSACE_##num##_DEVICE_ID, \ + .num_resources = 2, \ + .resource = (struct resource[]) { \ + { \ + .start = XPAR_SYSACE_##num##_BASEADDR, \ + .end = XPAR_SYSACE_##num##_HIGHADDR, \ + .flags = IORESOURCE_MEM, \ + }, \ + { \ + .start = XPAR_INTC_0_SYSACE_##num##_VEC_ID, \ + .flags = IORESOURCE_IRQ, \ + }, \ + }, \ +} + + +/* UART 8250 driver platform data table */ +struct plat_serial8250_port virtex_serial_platform_data[] = { +#if defined(XPAR_UARTNS550_0_BASEADDR) + XPAR_UART(0), +#endif +#if defined(XPAR_UARTNS550_1_BASEADDR) + XPAR_UART(1), +#endif +#if defined(XPAR_UARTNS550_2_BASEADDR) + XPAR_UART(2), +#endif +#if defined(XPAR_UARTNS550_3_BASEADDR) + XPAR_UART(3), +#endif +#if defined(XPAR_UARTNS550_4_BASEADDR) + XPAR_UART(4), +#endif +#if defined(XPAR_UARTNS550_5_BASEADDR) + XPAR_UART(5), +#endif +#if defined(XPAR_UARTNS550_6_BASEADDR) + XPAR_UART(6), +#endif +#if defined(XPAR_UARTNS550_7_BASEADDR) + XPAR_UART(7), +#endif + { }, /* terminated by empty record */ +}; + + +struct platform_device virtex_platform_devices[] = { + /* UARTLITE instances */ +#if defined(XPAR_UARTLITE_0_BASEADDR) + XPAR_UARTLITE(0), +#endif +#if defined(XPAR_UARTLITE_1_BASEADDR) + XPAR_UARTLITE(1), +#endif +#if defined(XPAR_UARTLITE_2_BASEADDR) + XPAR_UARTLITE(2), +#endif +#if defined(XPAR_UARTLITE_3_BASEADDR) + XPAR_UARTLITE(3), +#endif +#if defined(XPAR_UARTLITE_4_BASEADDR) + XPAR_UARTLITE(4), +#endif +#if defined(XPAR_UARTLITE_5_BASEADDR) + XPAR_UARTLITE(5), +#endif +#if defined(XPAR_UARTLITE_6_BASEADDR) + XPAR_UARTLITE(6), +#endif +#if defined(XPAR_UARTLITE_7_BASEADDR) + XPAR_UARTLITE(7), +#endif + + /* Full UART instances */ +#if defined(XPAR_UARTNS550_0_BASEADDR) + { + .name = "serial8250", + .id = 0, + .dev.platform_data = virtex_serial_platform_data, + }, +#endif + + /* SystemACE instances */ +#if defined(XPAR_SYSACE_0_BASEADDR) + XPAR_SYSACE(0), +#endif +#if defined(XPAR_SYSACE_1_BASEADDR) + XPAR_SYSACE(1), +#endif + + /* ML300/403 reference design framebuffer */ +#if defined(XPAR_TFT_0_BASEADDR) + { + .name = "xilinxfb", + .id = 0, + .num_resources = 1, + .resource = (struct resource[]) { + { + .start = XPAR_TFT_0_BASEADDR, + .end = XPAR_TFT_0_BASEADDR+7, + .flags = IORESOURCE_IO, + }, + }, + }, +#endif +}; + +/* Early serial support functions */ +static void __init +virtex_early_serial_init(int num, struct plat_serial8250_port *pdata) +{ +#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) + struct uart_port serial_req; + + memset(&serial_req, 0, sizeof(serial_req)); + serial_req.mapbase = pdata->mapbase; + serial_req.membase = pdata->membase; + serial_req.irq = pdata->irq; + serial_req.uartclk = pdata->uartclk; + serial_req.regshift = pdata->regshift; + serial_req.iotype = pdata->iotype; + serial_req.flags = pdata->flags; + gen550_init(num, &serial_req); +#endif +} + +void __init +virtex_early_serial_map(void) +{ +#ifdef CONFIG_SERIAL_8250 + struct plat_serial8250_port *pdata; + int i = 0; + + pdata = virtex_serial_platform_data; + while(pdata && pdata->flags) { + pdata->membase = ioremap(pdata->mapbase, 0x100); + virtex_early_serial_init(i, pdata); + pdata++; + i++; + } +#endif /* CONFIG_SERIAL_8250 */ +} + +/* + * default fixup routine; do nothing and return success. + * + * Reimplement this routine in your custom board support file to + * override the default behaviour + */ +int __attribute__ ((weak)) +virtex_device_fixup(struct platform_device *dev) +{ + return 0; +} + +static int __init virtex_init(void) +{ + struct platform_device *index = virtex_platform_devices; + unsigned int ret = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(virtex_platform_devices); i++, index++) { + if (virtex_device_fixup(index) != 0) + continue; + + if (platform_device_register(index)) { + ret = 1; + printk(KERN_ERR "cannot register dev %s:%d\n", + index->name, index->id); + } + } + return ret; +} + +subsys_initcall(virtex_init); diff --git a/arch/ppc/syslib/virtex_devices.h b/arch/ppc/syslib/virtex_devices.h new file mode 100644 index 0000000..4a17dd3 --- /dev/null +++ b/arch/ppc/syslib/virtex_devices.h @@ -0,0 +1,27 @@ +/* + * Common support header for virtex ppc405 platforms + * + * Copyright 2007 Secret Lab Technologies Ltd. + * + * 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 __ASM_VIRTEX_DEVICES_H__ +#define __ASM_VIRTEX_DEVICES_H__ + +#include <linux/platform_device.h> + +void __init virtex_early_serial_map(void); + +/* Prototype for device fixup routine. Implement this routine in the + * board specific fixup code and the generic setup code will call it for + * each device is the platform device list. + * + * If the hook returns a non-zero value, then the device will not get + * registered with the platform bus + */ +int virtex_device_fixup(struct platform_device *dev); + +#endif /* __ASM_VIRTEX_DEVICES_H__ */ diff --git a/drivers/char/briq_panel.c b/drivers/char/briq_panel.c index 8dcf9d2..c70d52a 100644 --- a/drivers/char/briq_panel.c +++ b/drivers/char/briq_panel.c @@ -202,13 +202,16 @@ static struct miscdevice briq_panel_miscdev = { static int __init briq_panel_init(void) { - struct device_node *root = find_path_device("/"); + struct device_node *root = of_find_node_by_path("/"); const char *machine; int i; machine = get_property(root, "model", NULL); - if (!machine || strncmp(machine, "TotalImpact,BRIQ-1", 18) != 0) + if (!machine || strncmp(machine, "TotalImpact,BRIQ-1", 18) != 0) { + of_node_put(root); return -ENODEV; + } + of_node_put(root); printk(KERN_INFO "briq_panel: v%s Dr. Karsten Jeppesen (kj@totalimpact.com)\n", diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index a0a88aa2..0f9ed7b 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c @@ -47,8 +47,6 @@ #define HVC_MAJOR 229 #define HVC_MINOR 0 -#define TIMEOUT (10) - /* * Wait this long per iteration while trying to push buffered data to the * hypervisor before allowing the tty to complete a close operation. @@ -104,12 +102,12 @@ static DEFINE_SPINLOCK(hvc_structs_lock); /* * This value is used to assign a tty->index value to a hvc_struct based * upon order of exposure via hvc_probe(), when we can not match it to - * a console canidate registered with hvc_instantiate(). + * a console candidate registered with hvc_instantiate(). */ static int last_hvc = -1; /* - * Do not call this function with either the hvc_strucst_lock or the hvc_struct + * Do not call this function with either the hvc_structs_lock or the hvc_struct * lock held. If successful, this function increments the kobject reference * count against the target hvc_struct so it should be released when finished. */ @@ -162,7 +160,7 @@ void hvc_console_print(struct console *co, const char *b, unsigned count) if (index >= MAX_NR_HVC_CONSOLES) return; - /* This console adapter was removed so it is not useable. */ + /* This console adapter was removed so it is not usable. */ if (vtermnos[index] < 0) return; @@ -220,7 +218,7 @@ struct console hvc_con_driver = { }; /* - * Early console initialization. Preceeds driver initialization. + * Early console initialization. Precedes driver initialization. * * (1) we are first, and the user specified another driver * -- index will remain -1 @@ -257,7 +255,7 @@ int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops) if (vtermnos[index] != -1) return -1; - /* make sure no no tty has been registerd in this index */ + /* make sure no no tty has been registered in this index */ hp = hvc_get_by_index(index); if (hp) { kobject_put(&hp->kobj); @@ -267,7 +265,7 @@ int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops) vtermnos[index] = vtermno; cons_ops[index] = ops; - /* reserve all indices upto and including this index */ + /* reserve all indices up to and including this index */ if (last_hvc < index) last_hvc = index; @@ -528,7 +526,7 @@ static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count /* * This is actually a contract between the driver and the tty layer outlining - * how much write room the driver can guarentee will be sent OR BUFFERED. This + * how much write room the driver can guarantee will be sent OR BUFFERED. This * driver MUST honor the return value. */ static int hvc_write_room(struct tty_struct *tty) @@ -550,6 +548,18 @@ static int hvc_chars_in_buffer(struct tty_struct *tty) return hp->n_outbuf; } +/* + * timeout will vary between the MIN and MAX values defined here. By default + * and during console activity we will use a default MIN_TIMEOUT of 10. When + * the console is idle, we increase the timeout value on each pass through + * msleep until we reach the max. This may be noticeable as a brief (average + * one second) delay on the console before the console responds to input when + * there has been no input for some time. + */ +#define MIN_TIMEOUT (10) +#define MAX_TIMEOUT (2000) +static u32 timeout = MIN_TIMEOUT; + #define HVC_POLL_READ 0x00000001 #define HVC_POLL_WRITE 0x00000002 @@ -642,9 +652,14 @@ static int hvc_poll(struct hvc_struct *hp) bail: spin_unlock_irqrestore(&hp->lock, flags); - if (read_total) + if (read_total) { + /* Activity is occurring, so reset the polling backoff value to + a minimum for performance. */ + timeout = MIN_TIMEOUT; + tty_flip_buffer_push(tty); - + } + return poll_mask; } @@ -688,8 +703,12 @@ int khvcd(void *unused) if (!hvc_kicked) { if (poll_mask == 0) schedule(); - else - msleep_interruptible(TIMEOUT); + else { + if (timeout < MAX_TIMEOUT) + timeout += (timeout >> 6) + 1; + + msleep_interruptible(timeout); + } } __set_current_state(TASK_RUNNING); } while (!kthread_should_stop()); @@ -794,7 +813,7 @@ int __devexit hvc_remove(struct hvc_struct *hp) /* * We 'put' the instance that was grabbed when the kobject instance - * was intialized using kobject_init(). Let the last holder of this + * was initialized using kobject_init(). Let the last holder of this * kobject cause it to be removed, which will probably be the tty_hangup * below. */ @@ -850,7 +869,7 @@ int __init hvc_init(void) } module_init(hvc_init); -/* This isn't particularily necessary due to this being a console driver +/* This isn't particularly necessary due to this being a console driver * but it is nice to be thorough. */ static void __exit hvc_exit(void) diff --git a/drivers/char/hvc_iseries.c b/drivers/char/hvc_iseries.c index f144a94..ec420fe 100644 --- a/drivers/char/hvc_iseries.c +++ b/drivers/char/hvc_iseries.c @@ -575,7 +575,7 @@ static int hvc_find_vtys(void) (num_found >= VTTY_PORTS)) break; - vtermno = get_property(vty, "reg", NULL); + vtermno = of_get_property(vty, "reg", NULL); if (!vtermno) continue; diff --git a/drivers/char/hvc_vio.c b/drivers/char/hvc_vio.c index f9c0084..94a542e 100644 --- a/drivers/char/hvc_vio.c +++ b/drivers/char/hvc_vio.c @@ -153,7 +153,7 @@ static int hvc_find_vtys(void) if (num_found >= MAX_NR_HVC_CONSOLES) break; - vtermno = get_property(vty, "reg", NULL); + vtermno = of_get_property(vty, "reg", NULL); if (!vtermno) continue; diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c index 50315d6..d5a752d 100644 --- a/drivers/char/hvsi.c +++ b/drivers/char/hvsi.c @@ -1279,8 +1279,8 @@ static int __init hvsi_console_init(void) struct hvsi_struct *hp; const uint32_t *vtermno, *irq; - vtermno = get_property(vty, "reg", NULL); - irq = get_property(vty, "interrupts", NULL); + vtermno = of_get_property(vty, "reg", NULL); + irq = of_get_property(vty, "interrupts", NULL); if (!vtermno || !irq) continue; diff --git a/drivers/char/tpm/tpm_atmel.h b/drivers/char/tpm/tpm_atmel.h index aefd683..3c85200 100644 --- a/drivers/char/tpm/tpm_atmel.h +++ b/drivers/char/tpm/tpm_atmel.h @@ -53,8 +53,8 @@ static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size) } reg = get_property(dn, "reg", ®len); - naddrc = prom_n_addr_cells(dn); - nsizec = prom_n_size_cells(dn); + naddrc = of_n_addr_cells(dn); + nsizec = of_n_size_cells(dn); of_node_put(dn); diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index e812aa1..60198a7 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig @@ -548,7 +548,7 @@ config MV64X60_WDT depends on WATCHDOG && MV64X60 config BOOKE_WDT - tristate "PowerPC Book-E Watchdog Timer" + bool "PowerPC Book-E Watchdog Timer" depends on WATCHDOG && (BOOKE || 4xx) ---help--- Please see Documentation/watchdog/watchdog-api.txt for diff --git a/drivers/hwmon/ams/ams-core.c b/drivers/hwmon/ams/ams-core.c index f1f0f5d..f5ebad5 100644 --- a/drivers/hwmon/ams/ams-core.c +++ b/drivers/hwmon/ams/ams-core.c @@ -141,10 +141,10 @@ static void ams_worker(struct work_struct *work) int ams_sensor_attach(void) { int result; - u32 *prop; + const u32 *prop; /* Get orientation */ - prop = (u32*)get_property(ams_info.of_node, "orientation", NULL); + prop = get_property(ams_info.of_node, "orientation", NULL); if (!prop) return -ENODEV; ams_info.orient1 = *prop; diff --git a/drivers/hwmon/ams/ams-i2c.c b/drivers/hwmon/ams/ams-i2c.c index 0d24bdf..485d333 100644 --- a/drivers/hwmon/ams/ams-i2c.c +++ b/drivers/hwmon/ams/ams-i2c.c @@ -263,7 +263,7 @@ int __init ams_i2c_init(struct device_node *np) { char *tmp_bus; int result; - u32 *prop; + const u32 *prop; mutex_lock(&ams_info.lock); @@ -276,7 +276,7 @@ int __init ams_i2c_init(struct device_node *np) ams_info.bustype = BUS_I2C; /* look for bus either using "reg" or by path */ - prop = (u32*)get_property(ams_info.of_node, "reg", NULL); + prop = get_property(ams_info.of_node, "reg", NULL); if (!prop) { result = -ENODEV; diff --git a/drivers/hwmon/ams/ams-pmu.c b/drivers/hwmon/ams/ams-pmu.c index 4636ae0..1b01c21 100644 --- a/drivers/hwmon/ams/ams-pmu.c +++ b/drivers/hwmon/ams/ams-pmu.c @@ -146,7 +146,7 @@ static void ams_pmu_exit(void) int __init ams_pmu_init(struct device_node *np) { - u32 *prop; + const u32 *prop; int result; mutex_lock(&ams_info.lock); @@ -160,7 +160,7 @@ int __init ams_pmu_init(struct device_node *np) ams_info.bustype = BUS_HOST; /* Get PMU command, should be 0x4e, but we can never know */ - prop = (u32*)get_property(ams_info.of_node, "reg", NULL); + prop = get_property(ams_info.of_node, "reg", NULL); if (!prop) { result = -ENODEV; goto exit; diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c index 3b23d67..4700085 100644 --- a/drivers/infiniband/hw/ehca/ehca_main.c +++ b/drivers/infiniband/hw/ehca/ehca_main.c @@ -565,11 +565,11 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev, const struct of_device_id *id) { struct ehca_shca *shca; - u64 *handle; + const u64 *handle; struct ib_pd *ibpd; int ret; - handle = (u64 *)get_property(dev->ofdev.node, "ibm,hca-handle", NULL); + handle = get_property(dev->ofdev.node, "ibm,hca-handle", NULL); if (!handle) { ehca_gen_err("Cannot get eHCA handle for adapter: %s.", dev->ofdev.node->full_name); diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c index f729eeb..adfea3c 100644 --- a/drivers/macintosh/adb.c +++ b/drivers/macintosh/adb.c @@ -90,7 +90,7 @@ static int autopoll_devs; int __adb_probe_sync; #ifdef CONFIG_PM -static int adb_notify_sleep(struct pmu_sleep_notifier *self, int when); +static void adb_notify_sleep(struct pmu_sleep_notifier *self, int when); static struct pmu_sleep_notifier adb_sleep_notifier = { adb_notify_sleep, SLEEP_LEVEL_ADB, @@ -340,11 +340,9 @@ __initcall(adb_init); /* * notify clients before sleep and reset bus afterwards */ -int +void adb_notify_sleep(struct pmu_sleep_notifier *self, int when) { - int ret; - switch (when) { case PBOOK_SLEEP_REQUEST: adb_got_sleep = 1; @@ -353,22 +351,8 @@ adb_notify_sleep(struct pmu_sleep_notifier *self, int when) /* Stop autopoll */ if (adb_controller->autopoll) adb_controller->autopoll(0); - ret = blocking_notifier_call_chain(&adb_client_list, - ADB_MSG_POWERDOWN, NULL); - if (ret & NOTIFY_STOP_MASK) { - up(&adb_probe_mutex); - return PBOOK_SLEEP_REFUSE; - } - break; - case PBOOK_SLEEP_REJECT: - if (adb_got_sleep) { - adb_got_sleep = 0; - up(&adb_probe_mutex); - adb_reset_bus(); - } - break; - - case PBOOK_SLEEP_NOW: + blocking_notifier_call_chain(&adb_client_list, + ADB_MSG_POWERDOWN, NULL); break; case PBOOK_WAKE: adb_got_sleep = 0; @@ -376,14 +360,13 @@ adb_notify_sleep(struct pmu_sleep_notifier *self, int when) adb_reset_bus(); break; } - return PBOOK_SLEEP_OK; } #endif /* CONFIG_PM */ static int do_adb_reset_bus(void) { - int ret, nret; + int ret; if (adb_controller == NULL) return -ENXIO; @@ -391,13 +374,8 @@ do_adb_reset_bus(void) if (adb_controller->autopoll) adb_controller->autopoll(0); - nret = blocking_notifier_call_chain(&adb_client_list, - ADB_MSG_PRE_RESET, NULL); - if (nret & NOTIFY_STOP_MASK) { - if (adb_controller->autopoll) - adb_controller->autopoll(autopoll_devs); - return -EBUSY; - } + blocking_notifier_call_chain(&adb_client_list, + ADB_MSG_PRE_RESET, NULL); if (sleepy_trackpad) { /* Let the trackpad settle down */ @@ -427,10 +405,8 @@ do_adb_reset_bus(void) } up(&adb_handler_sem); - nret = blocking_notifier_call_chain(&adb_client_list, - ADB_MSG_POST_RESET, NULL); - if (nret & NOTIFY_STOP_MASK) - return -EBUSY; + blocking_notifier_call_chain(&adb_client_list, + ADB_MSG_POST_RESET, NULL); return ret; } diff --git a/drivers/macintosh/ans-lcd.c b/drivers/macintosh/ans-lcd.c index cdd5a0f..e54c4d9 100644 --- a/drivers/macintosh/ans-lcd.c +++ b/drivers/macintosh/ans-lcd.c @@ -145,11 +145,12 @@ anslcd_init(void) int retval; struct device_node* node; - node = find_devices("lcd"); - if (!node || !node->parent) - return -ENODEV; - if (strcmp(node->parent->name, "gc")) + node = of_find_node_by_name(NULL, "lcd"); + if (!node || !node->parent || strcmp(node->parent->name, "gc")) { + of_node_put(node); return -ENODEV; + } + of_node_put(node); anslcd_ptr = ioremap(ANSLCD_ADDR, 0x20); diff --git a/drivers/macintosh/apm_emu.c b/drivers/macintosh/apm_emu.c index c5e4d43..cdb0bea 100644 --- a/drivers/macintosh/apm_emu.c +++ b/drivers/macintosh/apm_emu.c @@ -96,7 +96,7 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue); static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue); static struct apm_user * user_list; -static int apm_notify_sleep(struct pmu_sleep_notifier *self, int when); +static void apm_notify_sleep(struct pmu_sleep_notifier *self, int when); static struct pmu_sleep_notifier apm_sleep_notifier = { apm_notify_sleep, SLEEP_LEVEL_USERLAND, @@ -352,7 +352,7 @@ static int do_open(struct inode * inode, struct file * filp) * doesn't provide a way to NAK, but this could be added * here. */ -static int wait_all_suspend(void) +static void wait_all_suspend(void) { DECLARE_WAITQUEUE(wait, current); @@ -366,24 +366,19 @@ static int wait_all_suspend(void) remove_wait_queue(&apm_suspend_waitqueue, &wait); DBG("apm_emu: wait_all_suspend() - complete !\n"); - - return 1; } -static int apm_notify_sleep(struct pmu_sleep_notifier *self, int when) +static void apm_notify_sleep(struct pmu_sleep_notifier *self, int when) { switch(when) { case PBOOK_SLEEP_REQUEST: queue_event(APM_SYS_SUSPEND, NULL); - if (!wait_all_suspend()) - return PBOOK_SLEEP_REFUSE; + wait_all_suspend(); break; - case PBOOK_SLEEP_REJECT: case PBOOK_WAKE: queue_event(APM_NORMAL_RESUME, NULL); break; } - return PBOOK_SLEEP_OK; } #define APM_CRITICAL 10 diff --git a/drivers/macintosh/mac_hid.c b/drivers/macintosh/mac_hid.c index c1fd816..1599dc3 100644 --- a/drivers/macintosh/mac_hid.c +++ b/drivers/macintosh/mac_hid.c @@ -102,8 +102,6 @@ int mac_hid_mouse_emulate_buttons(int caller, unsigned int keycode, int down) return 0; } -EXPORT_SYMBOL(mac_hid_mouse_emulate_buttons); - static int emumousebtn_input_register(void) { int ret; diff --git a/drivers/macintosh/macio-adb.c b/drivers/macintosh/macio-adb.c index 026b67f..79119f5 100644 --- a/drivers/macintosh/macio-adb.c +++ b/drivers/macintosh/macio-adb.c @@ -82,7 +82,14 @@ struct adb_driver macio_adb_driver = { int macio_probe(void) { - return find_compatible_devices("adb", "chrp,adb0")? 0: -ENODEV; + struct device_node *np; + + np = of_find_compatible_node(NULL, "adb", "chrp,adb0"); + if (np) { + of_node_put(np); + return 0; + } + return -ENODEV; } int macio_init(void) @@ -91,12 +98,14 @@ int macio_init(void) struct resource r; unsigned int irq; - adbs = find_compatible_devices("adb", "chrp,adb0"); + adbs = of_find_compatible_node(NULL, "adb", "chrp,adb0"); if (adbs == 0) return -ENXIO; - if (of_address_to_resource(adbs, 0, &r)) + if (of_address_to_resource(adbs, 0, &r)) { + of_node_put(adbs); return -ENXIO; + } adb = ioremap(r.start, sizeof(struct adb_regs)); out_8(&adb->ctrl.r, 0); @@ -107,6 +116,7 @@ int macio_init(void) out_8(&adb->autopoll.r, APE); irq = irq_of_parse_and_map(adbs, 0); + of_node_put(adbs); if (request_irq(irq, macio_adb_interrupt, 0, "ADB", (void *)0)) { printk(KERN_ERR "ADB: can't get irq %d\n", irq); return -EAGAIN; diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index d562160..c96b7fe 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c @@ -134,108 +134,12 @@ static int macio_device_resume(struct device * dev) return 0; } -static int macio_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) -{ - struct macio_dev * macio_dev; - struct of_device * of; - char *scratch; - const char *compat, *compat2; - - int i = 0; - int length, cplen, cplen2, seen = 0; - - if (!dev) - return -ENODEV; - - macio_dev = to_macio_device(dev); - if (!macio_dev) - return -ENODEV; - - of = &macio_dev->ofdev; - - /* stuff we want to pass to /sbin/hotplug */ - envp[i++] = scratch = buffer; - length = scnprintf (scratch, buffer_size, "OF_NAME=%s", of->node->name); - ++length; - buffer_size -= length; - if ((buffer_size <= 0) || (i >= num_envp)) - return -ENOMEM; - scratch += length; - - envp[i++] = scratch; - length = scnprintf (scratch, buffer_size, "OF_TYPE=%s", of->node->type); - ++length; - buffer_size -= length; - if ((buffer_size <= 0) || (i >= num_envp)) - return -ENOMEM; - scratch += length; - - /* 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 = get_property(of->node, "compatible", &cplen); - compat2 = compat; - cplen2= cplen; - while (compat && cplen > 0) { - envp[i++] = scratch; - length = scnprintf (scratch, buffer_size, - "OF_COMPATIBLE_%d=%s", seen, compat); - ++length; - buffer_size -= length; - if ((buffer_size <= 0) || (i >= num_envp)) - return -ENOMEM; - scratch += length; - length = strlen (compat) + 1; - compat += length; - cplen -= length; - seen++; - } - - envp[i++] = scratch; - length = scnprintf (scratch, buffer_size, "OF_COMPATIBLE_N=%d", seen); - ++length; - buffer_size -= length; - if ((buffer_size <= 0) || (i >= num_envp)) - return -ENOMEM; - scratch += length; - - envp[i++] = scratch; - length = scnprintf (scratch, buffer_size, "MODALIAS=of:N%sT%s", - of->node->name, of->node->type); - /* overwrite '\0' */ - buffer_size -= length; - if ((buffer_size <= 0) || (i >= num_envp)) - return -ENOMEM; - scratch += length; - - if (!compat2) { - compat2 = ""; - cplen2 = 1; - } - while (cplen2 > 0) { - length = snprintf (scratch, buffer_size, "C%s", compat2); - buffer_size -= length; - if (buffer_size <= 0) - return -ENOMEM; - scratch += length; - length = strlen (compat2) + 1; - compat2 += length; - cplen2 -= length; - } - - envp[i] = NULL; - - return 0; -} - extern struct device_attribute macio_dev_attrs[]; struct bus_type macio_bus_type = { .name = "macio", .match = macio_bus_match, - .uevent = macio_uevent, + .uevent = of_device_uevent, .probe = macio_device_probe, .remove = macio_device_remove, .shutdown = macio_device_shutdown, @@ -491,7 +395,7 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, #endif MAX_NODE_NAME_SIZE, np->name); } else { - reg = get_property(np, "reg", NULL); + reg = of_get_property(np, "reg", NULL); sprintf(dev->ofdev.dev.bus_id, "%1d.%08x:%.*s", chip->lbus.index, reg ? *reg : 0, MAX_NODE_NAME_SIZE, np->name); diff --git a/drivers/macintosh/macio_sysfs.c b/drivers/macintosh/macio_sysfs.c index 8566bdf..cc82679 100644 --- a/drivers/macintosh/macio_sysfs.c +++ b/drivers/macintosh/macio_sysfs.c @@ -21,7 +21,7 @@ compatible_show (struct device *dev, struct device_attribute *attr, char *buf) int length = 0; of = &to_macio_device (dev)->ofdev; - compat = get_property(of->node, "compatible", &cplen); + compat = of_get_property(of->node, "compatible", &cplen); if (!compat) { *buf = '\0'; return 0; @@ -47,18 +47,20 @@ static ssize_t modalias_show (struct device *dev, struct device_attribute *attr, int length; of = &to_macio_device (dev)->ofdev; - compat = get_property(of->node, "compatible", &cplen); + compat = of_get_property(of->node, "compatible", &cplen); if (!compat) compat = "", cplen = 1; length = sprintf (buf, "of:N%sT%s", of->node->name, of->node->type); buf += length; while (cplen > 0) { int l; - length += sprintf (buf, "C%s", compat); - buf += length; + l = sprintf (buf, "C%s", compat); + length += l; + buf += l; l = strlen (compat) + 1; compat += l; cplen -= l; } + length += sprintf(buf, "\n"); return length; } diff --git a/drivers/macintosh/rack-meter.c b/drivers/macintosh/rack-meter.c index f83fad2..4177ff0 100644 --- a/drivers/macintosh/rack-meter.c +++ b/drivers/macintosh/rack-meter.c @@ -387,7 +387,7 @@ static int __devinit rackmeter_probe(struct macio_dev* mdev, if (strcmp(np->name, "lightshow") == 0) break; if ((strcmp(np->name, "sound") == 0) && - get_property(np, "virtual", NULL) != NULL) + of_get_property(np, "virtual", NULL) != NULL) break; } if (np == NULL) { diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index c9f3dc4..a98a328 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -491,7 +491,7 @@ int __init smu_init (void) printk(KERN_ERR "SMU: Can't find doorbell GPIO !\n"); goto fail; } - data = get_property(smu->db_node, "reg", NULL); + data = of_get_property(smu->db_node, "reg", NULL); if (data == NULL) { of_node_put(smu->db_node); smu->db_node = NULL; @@ -512,7 +512,7 @@ int __init smu_init (void) smu->msg_node = of_find_node_by_name(NULL, "smu-interrupt"); if (smu->msg_node == NULL) break; - data = get_property(smu->msg_node, "reg", NULL); + data = of_get_property(smu->msg_node, "reg", NULL); if (data == NULL) { of_node_put(smu->msg_node); smu->msg_node = NULL; @@ -952,7 +952,7 @@ static struct smu_sdbp_header *smu_create_sdb_partition(int id) prop->name = ((char *)prop) + tlen - 18; sprintf(prop->name, "sdb-partition-%02x", id); prop->length = len; - prop->value = (unsigned char *)hdr; + prop->value = hdr; prop->next = NULL; /* Read the datablock */ @@ -1004,7 +1004,7 @@ const struct smu_sdbp_header *__smu_get_sdb_partition(int id, } else mutex_lock(&smu_part_access); - part = get_property(smu->of_node, pname, size); + part = of_get_property(smu->of_node, pname, size); if (part == NULL) { DPRINTK("trying to extract from SMU ...\n"); part = smu_create_sdb_partition(id); diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c index a7ce5592..2289034 100644 --- a/drivers/macintosh/therm_adt746x.c +++ b/drivers/macintosh/therm_adt746x.c @@ -567,13 +567,13 @@ thermostat_init(void) else return -ENODEV; - prop = get_property(np, "hwsensor-params-version", NULL); + prop = of_get_property(np, "hwsensor-params-version", NULL); printk(KERN_INFO "adt746x: version %d (%ssupported)\n", *prop, (*prop == 1)?"":"un"); if (*prop != 1) return -ENODEV; - prop = get_property(np, "reg", NULL); + prop = of_get_property(np, "reg", NULL); if (!prop) return -ENODEV; @@ -591,9 +591,9 @@ thermostat_init(void) "limit_adjust: %d, fan_speed: %d\n", therm_bus, therm_address, limit_adjust, fan_speed); - if (get_property(np, "hwsensor-location", NULL)) { + if (of_get_property(np, "hwsensor-location", NULL)) { for (i = 0; i < 3; i++) { - sensor_location[i] = get_property(np, + sensor_location[i] = of_get_property(np, "hwsensor-location", NULL) + offset; if (sensor_location[i] == NULL) diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c index 2e4ad44..78ff186 100644 --- a/drivers/macintosh/therm_pm72.c +++ b/drivers/macintosh/therm_pm72.c @@ -674,7 +674,7 @@ static int read_eeprom(int cpu, struct mpu_data *out) printk(KERN_ERR "therm_pm72: Failed to retrieve cpuid node from device-tree\n"); return -ENODEV; } - data = get_property(np, "cpuid", &len); + data = of_get_property(np, "cpuid", &len); if (data == NULL) { printk(KERN_ERR "therm_pm72: Failed to retrieve cpuid property from device-tree\n"); of_node_put(np); @@ -1337,7 +1337,7 @@ static int init_backside_state(struct backside_pid_state *state) */ u3 = of_find_node_by_path("/u3@0,f8000000"); if (u3 != NULL) { - const u32 *vers = get_property(u3, "device-rev", NULL); + const u32 *vers = of_get_property(u3, "device-rev", NULL); if (vers) if (((*vers) & 0x3f) < 0x34) u3h = 0; @@ -2129,8 +2129,8 @@ static void fcu_lookup_fans(struct device_node *fcu_node) continue; /* Lookup for a matching location */ - loc = get_property(np, "location", NULL); - reg = get_property(np, "reg", NULL); + loc = of_get_property(np, "location", NULL); + reg = of_get_property(np, "reg", NULL); if (loc == NULL || reg == NULL) continue; DBG(" matching location: %s, reg: 0x%08x\n", loc, *reg); diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c index a1d3a98..35233de 100644 --- a/drivers/macintosh/therm_windtunnel.c +++ b/drivers/macintosh/therm_windtunnel.c @@ -492,7 +492,7 @@ g4fan_init( void ) if( !(np=of_find_node_by_name(NULL, "power-mgt")) ) return -ENODEV; - info = get_property(np, "thermal-info", NULL); + info = of_get_property(np, "thermal-info", NULL); of_node_put(np); if( !info || !machine_is_compatible("PowerMac3,6") ) diff --git a/drivers/macintosh/via-cuda.c b/drivers/macintosh/via-cuda.c index d58fcf6..76d2177 100644 --- a/drivers/macintosh/via-cuda.c +++ b/drivers/macintosh/via-cuda.c @@ -131,7 +131,7 @@ int __init find_via_cuda(void) if (vias == 0) return 0; - reg = get_property(vias, "reg", NULL); + reg = of_get_property(vias, "reg", NULL); if (reg == NULL) { printk(KERN_ERR "via-cuda: No \"reg\" property !\n"); goto fail; diff --git a/drivers/macintosh/via-pmu-led.c b/drivers/macintosh/via-pmu-led.c index 179af10..fc89a70 100644 --- a/drivers/macintosh/via-pmu-led.c +++ b/drivers/macintosh/via-pmu-led.c @@ -81,7 +81,7 @@ static struct led_classdev pmu_led = { }; #ifdef CONFIG_PM -static int pmu_led_sleep_call(struct pmu_sleep_notifier *self, int when) +static void pmu_led_sleep_call(struct pmu_sleep_notifier *self, int when) { unsigned long flags; @@ -99,8 +99,6 @@ static int pmu_led_sleep_call(struct pmu_sleep_notifier *self, int when) break; } spin_unlock_irqrestore(&pmu_blink_lock, flags); - - return PBOOK_SLEEP_OK; } static struct pmu_sleep_notifier via_pmu_led_sleep_notif = { @@ -120,11 +118,13 @@ static int __init via_pmu_led_init(void) dt = of_find_node_by_path("/"); if (dt == NULL) return -ENODEV; - model = get_property(dt, "model", NULL); + model = of_get_property(dt, "model", NULL); if (model == NULL) return -ENODEV; if (strncmp(model, "PowerBook", strlen("PowerBook")) != 0 && - strncmp(model, "iBook", strlen("iBook")) != 0) { + strncmp(model, "iBook", strlen("iBook")) != 0 && + strcmp(model, "PowerMac7,2") != 0 && + strcmp(model, "PowerMac7,3") != 0) { of_node_put(dt); /* ignore */ return -ENODEV; diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index b6073bd..1729d3f 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -289,7 +289,7 @@ int __init find_via_pmu(void) if (vias == NULL) return 0; - reg = get_property(vias, "reg", NULL); + reg = of_get_property(vias, "reg", NULL); if (reg == NULL) { printk(KERN_ERR "via-pmu: No \"reg\" property !\n"); goto fail; @@ -319,10 +319,13 @@ int __init find_via_pmu(void) else if (device_is_compatible(vias->parent, "Keylargo") || device_is_compatible(vias->parent, "K2-Keylargo")) { struct device_node *gpiop; + struct device_node *adbp; u64 gaddr = OF_BAD_ADDR; pmu_kind = PMU_KEYLARGO_BASED; - pmu_has_adb = (find_type_devices("adb") != NULL); + adbp = of_find_node_by_type(NULL, "adb"); + pmu_has_adb = (adbp != NULL); + of_node_put(adbp); pmu_intr_mask = PMU_INT_PCEJECT | PMU_INT_SNDBRT | PMU_INT_ADB | @@ -331,7 +334,7 @@ int __init find_via_pmu(void) gpiop = of_find_node_by_name(NULL, "gpio"); if (gpiop) { - reg = get_property(gpiop, "reg", NULL); + reg = of_get_property(gpiop, "reg", NULL); if (reg) gaddr = of_translate_address(gpiop, reg); if (gaddr != OF_BAD_ADDR) @@ -484,10 +487,11 @@ static int __init via_pmu_dev_init(void) pmu_batteries[0].flags |= PMU_BATT_TYPE_SMART; pmu_batteries[1].flags |= PMU_BATT_TYPE_SMART; } else { - struct device_node* prim = find_devices("power-mgt"); + struct device_node* prim = + of_find_node_by_name(NULL, "power-mgt"); const u32 *prim_info = NULL; if (prim) - prim_info = get_property(prim, "prim-info", NULL); + prim_info = of_get_property(prim, "prim-info", NULL); if (prim_info) { /* Other stuffs here yet unknown */ pmu_battery_count = (prim_info[6] >> 16) & 0xff; @@ -495,6 +499,7 @@ static int __init via_pmu_dev_init(void) if (pmu_battery_count > 1) pmu_batteries[1].flags |= PMU_BATT_TYPE_SMART; } + of_node_put(prim); } #endif /* CONFIG_PPC32 */ @@ -1769,35 +1774,21 @@ EXPORT_SYMBOL(pmu_unregister_sleep_notifier); #if defined(CONFIG_PM) && defined(CONFIG_PPC32) /* Sleep is broadcast last-to-first */ -static int -broadcast_sleep(int when, int fallback) +static void broadcast_sleep(int when) { - int ret = PBOOK_SLEEP_OK; struct list_head *list; struct pmu_sleep_notifier *notifier; for (list = sleep_notifiers.prev; list != &sleep_notifiers; list = list->prev) { notifier = list_entry(list, struct pmu_sleep_notifier, list); - ret = notifier->notifier_call(notifier, when); - if (ret != PBOOK_SLEEP_OK) { - printk(KERN_DEBUG "sleep %d rejected by %p (%p)\n", - when, notifier, notifier->notifier_call); - for (; list != &sleep_notifiers; list = list->next) { - notifier = list_entry(list, struct pmu_sleep_notifier, list); - notifier->notifier_call(notifier, fallback); - } - return ret; - } + notifier->notifier_call(notifier, when); } - return ret; } /* Wake is broadcast first-to-last */ -static int -broadcast_wake(void) +static void broadcast_wake(void) { - int ret = PBOOK_SLEEP_OK; struct list_head *list; struct pmu_sleep_notifier *notifier; @@ -1806,7 +1797,6 @@ broadcast_wake(void) notifier = list_entry(list, struct pmu_sleep_notifier, list); notifier->notifier_call(notifier, PBOOK_WAKE); } - return ret; } /* @@ -2013,12 +2003,8 @@ pmac_suspend_devices(void) pm_prepare_console(); - /* Notify old-style device drivers & userland */ - ret = broadcast_sleep(PBOOK_SLEEP_REQUEST, PBOOK_SLEEP_REJECT); - if (ret != PBOOK_SLEEP_OK) { - printk(KERN_ERR "Sleep rejected by drivers\n"); - return -EBUSY; - } + /* Notify old-style device drivers */ + broadcast_sleep(PBOOK_SLEEP_REQUEST); /* Sync the disks. */ /* XXX It would be nice to have some way to ensure that @@ -2028,12 +2014,7 @@ pmac_suspend_devices(void) */ sys_sync(); - /* Sleep can fail now. May not be very robust but useful for debugging */ - ret = broadcast_sleep(PBOOK_SLEEP_NOW, PBOOK_WAKE); - if (ret != PBOOK_SLEEP_OK) { - printk(KERN_ERR "Driver sleep failed\n"); - return -EBUSY; - } + broadcast_sleep(PBOOK_SLEEP_NOW); /* Send suspend call to devices, hold the device core's dpm_sem */ ret = device_suspend(PMSG_SUSPEND); @@ -2154,7 +2135,7 @@ static int powerbook_sleep_grackle(void) int ret; struct pci_dev *grackle; - grackle = pci_find_slot(0, 0); + grackle = pci_get_bus_and_slot(0, 0); if (!grackle) return -ENODEV; @@ -2202,6 +2183,8 @@ static int powerbook_sleep_grackle(void) pmcr1 &= ~(GRACKLE_PM|GRACKLE_DOZE|GRACKLE_SLEEP|GRACKLE_NAP); pci_write_config_word(grackle, 0x70, pmcr1); + pci_dev_put(grackle); + /* Make sure the PMU is idle */ pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,0); restore_via_state(); diff --git a/drivers/macintosh/windfarm_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c index 3f7967f..ab4d1b6 100644 --- a/drivers/macintosh/windfarm_lm75_sensor.c +++ b/drivers/macintosh/windfarm_lm75_sensor.c @@ -176,7 +176,7 @@ static int wf_lm75_attach(struct i2c_adapter *adapter) for (dev = NULL; (dev = of_get_next_child(busnode, dev)) != NULL;) { const char *loc = - get_property(dev, "hwsensor-location", NULL); + of_get_property(dev, "hwsensor-location", NULL); u8 addr; /* We must re-match the adapter in order to properly check diff --git a/drivers/macintosh/windfarm_max6690_sensor.c b/drivers/macintosh/windfarm_max6690_sensor.c index eae1189..eaa74af 100644 --- a/drivers/macintosh/windfarm_max6690_sensor.c +++ b/drivers/macintosh/windfarm_max6690_sensor.c @@ -134,7 +134,7 @@ static int wf_max6690_attach(struct i2c_adapter *adapter) if (!device_is_compatible(dev, "max6690")) continue; addr = pmac_i2c_get_dev_addr(dev); - loc = get_property(dev, "hwsensor-location", NULL); + loc = of_get_property(dev, "hwsensor-location", NULL); if (loc == NULL || addr == 0) continue; printk("found max6690, loc=%s addr=0x%02x\n", loc, addr); diff --git a/drivers/macintosh/windfarm_smu_controls.c b/drivers/macintosh/windfarm_smu_controls.c index 31b750d..ff398ad 100644 --- a/drivers/macintosh/windfarm_smu_controls.c +++ b/drivers/macintosh/windfarm_smu_controls.c @@ -167,7 +167,7 @@ static struct smu_fan_control *smu_fan_create(struct device_node *node, if (fct == NULL) return NULL; fct->ctrl.ops = &smu_fan_ops; - l = get_property(node, "location", NULL); + l = of_get_property(node, "location", NULL); if (l == NULL) goto fail; @@ -224,17 +224,17 @@ static struct smu_fan_control *smu_fan_create(struct device_node *node, goto fail; /* Get min & max values*/ - v = get_property(node, "min-value", NULL); + v = of_get_property(node, "min-value", NULL); if (v == NULL) goto fail; fct->min = *v; - v = get_property(node, "max-value", NULL); + v = of_get_property(node, "max-value", NULL); if (v == NULL) goto fail; fct->max = *v; /* Get "reg" value */ - reg = get_property(node, "reg", NULL); + reg = of_get_property(node, "reg", NULL); if (reg == NULL) goto fail; fct->reg = *reg; diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c index 83f79de..9a6c2cf 100644 --- a/drivers/macintosh/windfarm_smu_sat.c +++ b/drivers/macintosh/windfarm_smu_sat.c @@ -241,7 +241,7 @@ static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev) char *name; int vsens[2], isens[2]; - reg = get_property(dev, "reg", NULL); + reg = of_get_property(dev, "reg", NULL); if (reg == NULL) return; addr = *reg; @@ -268,9 +268,9 @@ static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev) isens[0] = isens[1] = -1; child = NULL; while ((child = of_get_next_child(dev, child)) != NULL) { - reg = get_property(child, "reg", NULL); - type = get_property(child, "device_type", NULL); - loc = get_property(child, "location", NULL); + reg = of_get_property(child, "reg", NULL); + type = of_get_property(child, "device_type", NULL); + loc = of_get_property(child, "location", NULL); if (reg == NULL || loc == NULL) continue; diff --git a/drivers/macintosh/windfarm_smu_sensors.c b/drivers/macintosh/windfarm_smu_sensors.c index 01b4c50..9c567b9 100644 --- a/drivers/macintosh/windfarm_smu_sensors.c +++ b/drivers/macintosh/windfarm_smu_sensors.c @@ -204,8 +204,8 @@ static struct smu_ad_sensor *smu_ads_create(struct device_node *node) ads = kmalloc(sizeof(struct smu_ad_sensor), GFP_KERNEL); if (ads == NULL) return NULL; - c = get_property(node, "device_type", NULL); - l = get_property(node, "location", NULL); + c = of_get_property(node, "device_type", NULL); + l = of_get_property(node, "location", NULL); if (c == NULL || l == NULL) goto fail; @@ -255,7 +255,7 @@ static struct smu_ad_sensor *smu_ads_create(struct device_node *node) } else goto fail; - v = get_property(node, "reg", NULL); + v = of_get_property(node, "reg", NULL); if (v == NULL) goto fail; ads->reg = *v; diff --git a/drivers/media/video/planb.c b/drivers/media/video/planb.c index fe184f9..1455a8f 100644 --- a/drivers/media/video/planb.c +++ b/drivers/media/video/planb.c @@ -2160,7 +2160,7 @@ static int find_planb(void) if (!machine_is(powermac)) return 0; - planb_devices = find_devices("planb"); + planb_devices = of_find_node_by_name(NULL, "planb"); if (planb_devices == 0) { planb_num=0; printk(KERN_WARNING "PlanB: no device found!\n"); @@ -2175,12 +2175,14 @@ static int find_planb(void) if (planb_devices->n_addrs != 1) { printk (KERN_WARNING "PlanB: expecting 1 address for planb " "(got %d)", planb_devices->n_addrs); + of_node_put(planb_devices); return 0; } if (planb_devices->n_intrs == 0) { printk(KERN_WARNING "PlanB: no intrs for device %s\n", planb_devices->full_name); + of_node_put(planb_devices); return 0; } else { irq = planb_devices->intrs[0].line; @@ -2202,6 +2204,7 @@ static int find_planb(void) confreg = planb_devices->addrs[0].space & 0xff; old_base = planb_devices->addrs[0].address; new_base = 0xf1000000; + of_node_put(planb_devices); DEBUG("PlanB: Found on bus %d, dev %d, func %d, " "membase 0x%x (base reg. 0x%x)\n", diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index a3d46ea..890c85e 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2273,11 +2273,12 @@ config GFAR_NAPI depends on GIANFAR config UCC_GETH - tristate "Freescale QE UCC GETH" - depends on QUICC_ENGINE && UCC_FAST + tristate "Freescale QE Gigabit Ethernet" + depends on QUICC_ENGINE + select UCC_FAST help - This driver supports the Gigabit Ethernet mode of QE UCC. - QE can be found on MPC836x CPUs. + This driver supports the Gigabit Ethernet mode of the QUICC Engine, + which is available on some Freescale SOCs. config UGETH_NAPI bool "NAPI Support" diff --git a/drivers/scsi/ibmvscsi/ibmvstgt.c b/drivers/scsi/ibmvscsi/ibmvstgt.c index 4368ca0..a39a478 100644 --- a/drivers/scsi/ibmvscsi/ibmvstgt.c +++ b/drivers/scsi/ibmvscsi/ibmvstgt.c @@ -897,9 +897,9 @@ static int get_system_info(void) { struct device_node *rootdn; const char *id, *model, *name; - unsigned int *num; + const unsigned int *num; - rootdn = find_path_device("/"); + rootdn = of_find_node_by_path("/"); if (!rootdn) return -ENOENT; @@ -912,10 +912,11 @@ static int get_system_info(void) if (name) strncpy(partition_name, name, sizeof(partition_name)); - num = (unsigned int *) get_property(rootdn, "ibm,partition-no", NULL); + num = get_property(rootdn, "ibm,partition-no", NULL); if (num) partition_number = *num; + of_node_put(rootdn); return 0; } diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c index 227c0f2..0a533f3 100644 --- a/drivers/scsi/ibmvscsi/rpa_vscsi.c +++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c @@ -157,7 +157,7 @@ static void gather_partition_info(void) const unsigned int *p_number_ptr; /* Retrieve information about this partition */ - rootdn = find_path_device("/"); + rootdn = of_find_node_by_path("/"); if (!rootdn) { return; } @@ -169,6 +169,7 @@ static void gather_partition_info(void) p_number_ptr = get_property(rootdn, "ibm,partition-no", NULL); if (p_number_ptr) partition_number = *p_number_ptr; + of_node_put(rootdn); } static void set_adapter_info(struct ibmvscsi_host_data *hostdata) diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index 752ef07..be8d757 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c @@ -1467,7 +1467,8 @@ no_dma: if (ZS_IS_IRDA(uap)) uap->port_type = PMAC_SCC_IRDA; if (ZS_IS_INTMODEM(uap)) { - struct device_node* i2c_modem = find_devices("i2c-modem"); + struct device_node* i2c_modem = + of_find_node_by_name(NULL, "i2c-modem"); if (i2c_modem) { const char* mid = get_property(i2c_modem, "modem-id", NULL); @@ -1482,6 +1483,7 @@ no_dma: } printk(KERN_INFO "pmac_zilog: i2c-modem detected, id: %d\n", mid ? (*mid) : 0); + of_node_put(i2c_modem); } else { printk(KERN_INFO "pmac_zilog: serial modem detected\n"); } diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 8372ace..b1cb72c 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -396,7 +396,7 @@ config FB_ATARI config FB_OF bool "Open Firmware frame buffer device support" - depends on (FB = y) && (PPC64 || PPC_OF) + depends on (FB = y) && (PPC64 || PPC_OF) && (!PPC_PSERIES || PCI) select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index 9a2b0d6..c411293 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c @@ -1262,7 +1262,7 @@ static void radeon_pm_full_reset_sdram(struct radeonfb_info *rinfo) /* This is the code for the Aluminium PowerBooks M10 / iBooks M11 */ if (rinfo->family == CHIP_FAMILY_RV350) { u32 sdram_mode_reg = rinfo->save_regs[35]; - static u32 default_mrtable[] = + static const u32 default_mrtable[] = { 0x21320032, 0x21321000, 0xa1321000, 0x21321000, 0xffffffff, 0x21320032, 0xa1320032, 0x21320032, 0xffffffff, diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c index fd60dba..8b76273 100644 --- a/drivers/video/controlfb.c +++ b/drivers/video/controlfb.c @@ -179,12 +179,14 @@ MODULE_LICENSE("GPL"); int init_module(void) { struct device_node *dp; + int ret = -ENXIO; - dp = find_devices("control"); + dp = of_find_node_by_name(NULL, "control"); if (dp != 0 && !control_of_init(dp)) - return 0; + ret = 0; + of_node_put(dp); - return -ENXIO; + return ret; } void cleanup_module(void) @@ -589,16 +591,18 @@ static int __init control_init(void) { struct device_node *dp; char *option = NULL; + int ret = -ENXIO; if (fb_get_options("controlfb", &option)) return -ENODEV; control_setup(option); - dp = find_devices("control"); + dp = of_find_node_by_name(NULL, "control"); if (dp != 0 && !control_of_init(dp)) - return 0; + ret = 0; + of_node_put(dp); - return -ENXIO; + return ret; } module_init(control_init); diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c index abdf068..eca471bc 100644 --- a/fs/proc/proc_devtree.c +++ b/fs/proc/proc_devtree.c @@ -38,7 +38,7 @@ static int property_read_proc(char *page, char **start, off_t off, n = count; else *eof = 1; - memcpy(page, pp->value + off, n); + memcpy(page, (char *)pp->value + off, n); *start = page; return n; } diff --git a/include/asm-powerpc/asm-compat.h b/include/asm-powerpc/asm-compat.h index c89bd58..c19e736 100644 --- a/include/asm-powerpc/asm-compat.h +++ b/include/asm-powerpc/asm-compat.h @@ -78,6 +78,15 @@ #define PPC_STLCX stringify_in_c(stdcx.) #define PPC_CNTLZL stringify_in_c(cntlzd) +/* Move to CR, single-entry optimized version. Only available + * on POWER4 and later. + */ +#ifdef CONFIG_POWER4_ONLY +#define PPC_MTOCRF stringify_in_c(mtocrf) +#else +#define PPC_MTOCRF stringify_in_c(mtcrf) +#endif + #else /* 32-bit */ /* operations for longs and pointers */ @@ -89,6 +98,7 @@ #define PPC_LLARX stringify_in_c(lwarx) #define PPC_STLCX stringify_in_c(stwcx.) #define PPC_CNTLZL stringify_in_c(cntlzw) +#define PPC_MTOCRF stringify_in_c(mtcrf) #endif diff --git a/include/asm-powerpc/cacheflush.h b/include/asm-powerpc/cacheflush.h index 08e93e7..ba667a383 100644 --- a/include/asm-powerpc/cacheflush.h +++ b/include/asm-powerpc/cacheflush.h @@ -64,6 +64,12 @@ extern void flush_dcache_phys_range(unsigned long start, unsigned long stop); memcpy(dst, src, len) + +#ifdef CONFIG_DEBUG_PAGEALLOC +/* internal debugging function */ +void kernel_map_pages(struct page *page, int numpages, int enable); +#endif + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_CACHEFLUSH_H */ diff --git a/include/asm-powerpc/cell-pmu.h b/include/asm-powerpc/cell-pmu.h index 35b9577..8066eed 100644 --- a/include/asm-powerpc/cell-pmu.h +++ b/include/asm-powerpc/cell-pmu.h @@ -97,11 +97,6 @@ extern void cbe_disable_pm_interrupts(u32 cpu); extern u32 cbe_get_and_clear_pm_interrupts(u32 cpu); extern void cbe_sync_irq(int node); -/* Utility functions, macros */ -extern u32 cbe_get_hw_thread_id(int cpu); - -#define cbe_cpu_to_node(cpu) ((cpu) >> 1) - #define CBE_COUNT_SUPERVISOR_MODE 0 #define CBE_COUNT_HYPERVISOR_MODE 1 #define CBE_COUNT_PROBLEM_MODE 2 diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index e870b53..4345249 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -48,6 +48,7 @@ enum powerpc_oprofile_type { PPC_OPROFILE_G4 = 3, PPC_OPROFILE_BOOKE = 4, PPC_OPROFILE_CELL = 5, + PPC_OPROFILE_PA6T = 6, }; enum powerpc_pmc_type { @@ -223,6 +224,10 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ CPU_FTR_PPC_LE) +#define CPU_FTRS_750CL (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ + CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ + CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE) #define CPU_FTRS_750FX1 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ @@ -235,9 +240,9 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE) -#define CPU_FTRS_750GX (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \ - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | \ - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ +#define CPU_FTRS_750GX (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ + CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE) #define CPU_FTRS_7400_NOTAU (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ diff --git a/include/asm-powerpc/current.h b/include/asm-powerpc/current.h index b8708ae..e2c7f06 100644 --- a/include/asm-powerpc/current.h +++ b/include/asm-powerpc/current.h @@ -12,6 +12,7 @@ struct task_struct; #ifdef __powerpc64__ +#include <linux/stddef.h> #include <asm/paca.h> static inline struct task_struct *get_current(void) diff --git a/include/asm-powerpc/edac.h b/include/asm-powerpc/edac.h new file mode 100644 index 0000000..6ead88b --- /dev/null +++ b/include/asm-powerpc/edac.h @@ -0,0 +1,40 @@ +/* + * PPC EDAC common defs + * + * Author: Dave Jiang <djiang@mvista.com> + * + * 2007 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +#ifndef ASM_EDAC_H +#define ASM_EDAC_H +/* + * ECC atomic, DMA, SMP and interrupt safe scrub function. + * Implements the per arch atomic_scrub() that EDAC use for software + * ECC scrubbing. It reads memory and then writes back the original + * value, allowing the hardware to detect and correct memory errors. + */ +static __inline__ void atomic_scrub(void *va, u32 size) +{ + unsigned int *virt_addr = va; + unsigned int temp; + unsigned int i; + + for (i = 0; i < size / sizeof(*virt_addr); i++, virt_addr++) { + /* Very carefully read and write to memory atomically + * so we are interrupt, DMA and SMP safe. + */ + __asm__ __volatile__ ("\n\ + 1: lwarx %0,0,%1\n\ + stwcx. %0,0,%1\n\ + bne- 1b\n\ + isync" + : "=&r"(temp) + : "r"(virt_addr) + : "cr0", "memory"); + } +} + +#endif diff --git a/include/asm-powerpc/eeh_event.h b/include/asm-powerpc/eeh_event.h index dc6bf0f..cc3cb04 100644 --- a/include/asm-powerpc/eeh_event.h +++ b/include/asm-powerpc/eeh_event.h @@ -30,8 +30,6 @@ struct eeh_event { struct list_head list; struct device_node *dn; /* struct device node */ struct pci_dev *dev; /* affected device */ - enum pci_channel_state state; /* PCI bus state for the affected device */ - int time_unavail; /* milliseconds until device might be available */ }; /** @@ -46,9 +44,7 @@ struct eeh_event { * (from a workqueue). */ int eeh_send_failure_event (struct device_node *dn, - struct pci_dev *dev, - enum pci_channel_state state, - int time_unavail); + struct pci_dev *dev); /* Main recovery function */ struct pci_dn * handle_eeh_events (struct eeh_event *); diff --git a/include/asm-powerpc/ibmebus.h b/include/asm-powerpc/ibmebus.h index 6611211..87d396e 100644 --- a/include/asm-powerpc/ibmebus.h +++ b/include/asm-powerpc/ibmebus.h @@ -2,36 +2,37 @@ * IBM PowerPC eBus Infrastructure Support. * * Copyright (c) 2005 IBM Corporation + * Joachim Fenkes <fenkes@de.ibm.com> * Heiko J Schick <schickhj@de.ibm.com> - * + * * All rights reserved. * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. + * This source code is distributed under a dual license of GPL v2.0 and OpenIB + * BSD. * * OpenIB BSD License * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation * and/or other materials - * provided with the distribution. + * provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ @@ -46,12 +47,11 @@ extern struct bus_type ibmebus_bus_type; -struct ibmebus_dev { - const char *name; +struct ibmebus_dev { struct of_device ofdev; }; -struct ibmebus_driver { +struct ibmebus_driver { char *name; struct of_device_id *id_table; int (*probe) (struct ibmebus_dev *dev, const struct of_device_id *id); @@ -63,7 +63,7 @@ int ibmebus_register_driver(struct ibmebus_driver *drv); void ibmebus_unregister_driver(struct ibmebus_driver *drv); int ibmebus_request_irq(struct ibmebus_dev *dev, - u32 ist, + u32 ist, irq_handler_t handler, unsigned long irq_flags, const char * devname, void *dev_id); diff --git a/include/asm-powerpc/immap_86xx.h b/include/asm-powerpc/immap_86xx.h index d905b66..59b9e07 100644 --- a/include/asm-powerpc/immap_86xx.h +++ b/include/asm-powerpc/immap_86xx.h @@ -85,81 +85,6 @@ typedef struct ccsr_pci { char res19[472]; } ccsr_pci_t; -/* PCI Express Registers */ -typedef struct ccsr_pex { - uint pex_config_addr; /* 0x.000 - PCI Express Configuration Address Register */ - uint pex_config_data; /* 0x.004 - PCI Express Configuration Data Register */ - char res1[4]; - uint pex_otb_cpl_tor; /* 0x.00c - PCI Express Outbound completion timeout register */ - uint pex_conf_tor; /* 0x.010 - PCI Express configuration timeout register */ - char res2[12]; - uint pex_pme_mes_dr; /* 0x.020 - PCI Express PME and message detect register */ - uint pex_pme_mes_disr; /* 0x.024 - PCI Express PME and message disable register */ - uint pex_pme_mes_ier; /* 0x.028 - PCI Express PME and message interrupt enable register */ - uint pex_pmcr; /* 0x.02c - PCI Express power management command register */ - char res3[3024]; - uint pexotar0; /* 0x.c00 - PCI Express outbound translation address register 0 */ - uint pexotear0; /* 0x.c04 - PCI Express outbound translation extended address register 0*/ - char res4[8]; - uint pexowar0; /* 0x.c10 - PCI Express outbound window attributes register 0*/ - char res5[12]; - uint pexotar1; /* 0x.c20 - PCI Express outbound translation address register 1 */ - uint pexotear1; /* 0x.c24 - PCI Express outbound translation extended address register 1*/ - uint pexowbar1; /* 0x.c28 - PCI Express outbound window base address register 1*/ - char res6[4]; - uint pexowar1; /* 0x.c30 - PCI Express outbound window attributes register 1*/ - char res7[12]; - uint pexotar2; /* 0x.c40 - PCI Express outbound translation address register 2 */ - uint pexotear2; /* 0x.c44 - PCI Express outbound translation extended address register 2*/ - uint pexowbar2; /* 0x.c48 - PCI Express outbound window base address register 2*/ - char res8[4]; - uint pexowar2; /* 0x.c50 - PCI Express outbound window attributes register 2*/ - char res9[12]; - uint pexotar3; /* 0x.c60 - PCI Express outbound translation address register 3 */ - uint pexotear3; /* 0x.c64 - PCI Express outbound translation extended address register 3*/ - uint pexowbar3; /* 0x.c68 - PCI Express outbound window base address register 3*/ - char res10[4]; - uint pexowar3; /* 0x.c70 - PCI Express outbound window attributes register 3*/ - char res11[12]; - uint pexotar4; /* 0x.c80 - PCI Express outbound translation address register 4 */ - uint pexotear4; /* 0x.c84 - PCI Express outbound translation extended address register 4*/ - uint pexowbar4; /* 0x.c88 - PCI Express outbound window base address register 4*/ - char res12[4]; - uint pexowar4; /* 0x.c90 - PCI Express outbound window attributes register 4*/ - char res13[12]; - char res14[256]; - uint pexitar3; /* 0x.da0 - PCI Express inbound translation address register 3 */ - char res15[4]; - uint pexiwbar3; /* 0x.da8 - PCI Express inbound window base address register 3 */ - uint pexiwbear3; /* 0x.dac - PCI Express inbound window base extended address register 3 */ - uint pexiwar3; /* 0x.db0 - PCI Express inbound window attributes register 3 */ - char res16[12]; - uint pexitar2; /* 0x.dc0 - PCI Express inbound translation address register 2 */ - char res17[4]; - uint pexiwbar2; /* 0x.dc8 - PCI Express inbound window base address register 2 */ - uint pexiwbear2; /* 0x.dcc - PCI Express inbound window base extended address register 2 */ - uint pexiwar2; /* 0x.dd0 - PCI Express inbound window attributes register 2 */ - char res18[12]; - uint pexitar1; /* 0x.de0 - PCI Express inbound translation address register 2 */ - char res19[4]; - uint pexiwbar1; /* 0x.de8 - PCI Express inbound window base address register 2 */ - uint pexiwbear1; /* 0x.dec - PCI Express inbound window base extended address register 2 */ - uint pexiwar1; /* 0x.df0 - PCI Express inbound window attributes register 2 */ - char res20[12]; - uint pex_err_dr; /* 0x.e00 - PCI Express error detect register */ - char res21[4]; - uint pex_err_en; /* 0x.e08 - PCI Express error interrupt enable register */ - char res22[4]; - uint pex_err_disr; /* 0x.e10 - PCI Express error disable register */ - char res23[12]; - uint pex_err_cap_stat; /* 0x.e20 - PCI Express error capture status register */ - char res24[4]; - uint pex_err_cap_r0; /* 0x.e28 - PCI Express error capture register 0 */ - uint pex_err_cap_r1; /* 0x.e2c - PCI Express error capture register 0 */ - uint pex_err_cap_r2; /* 0x.e30 - PCI Express error capture register 0 */ - uint pex_err_cap_r3; /* 0x.e34 - PCI Express error capture register 0 */ -} ccsr_pex_t; - /* Global Utility Registers */ typedef struct ccsr_guts { uint porpllsr; /* 0x.0000 - POR PLL Ratio Status Register */ diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h index 301c9bb..350c9bd 100644 --- a/include/asm-powerpc/io.h +++ b/include/asm-powerpc/io.h @@ -11,7 +11,12 @@ /* Check of existence of legacy devices */ extern int check_legacy_ioport(unsigned long base_port); -#define PNPBIOS_BASE 0xf000 /* only relevant for PReP */ +#define I8042_DATA_REG 0x60 +#define FDC_BASE 0x3f0 +/* only relevant for PReP */ +#define _PIDXR 0x279 +#define _PNPWRP 0xa79 +#define PNPBIOS_BASE 0xf000 #include <linux/compiler.h> #include <asm/page.h> diff --git a/include/asm-powerpc/kprobes.h b/include/asm-powerpc/kprobes.h index 3a5dd49..f850ca7 100644 --- a/include/asm-powerpc/kprobes.h +++ b/include/asm-powerpc/kprobes.h @@ -87,6 +87,11 @@ extern void arch_remove_kprobe(struct kprobe *p); struct arch_specific_insn { /* copy of original instruction */ kprobe_opcode_t *insn; + /* + * Set in kprobes code, initially to 0. If the instruction can be + * eumulated, this is set to 1, if not, to -1. + */ + int boostable; }; struct prev_kprobe { diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h index 1b04e57..b204926 100644 --- a/include/asm-powerpc/machdep.h +++ b/include/asm-powerpc/machdep.h @@ -153,9 +153,6 @@ struct machdep_calls { */ long (*feature_call)(unsigned int feature, ...); - /* Check availability of legacy devices like i8042 */ - int (*check_legacy_ioport)(unsigned int baseport); - /* Get legacy PCI/IDE interrupt mapping */ int (*pci_get_legacy_ide_irq)(struct pci_dev *dev, int channel); diff --git a/include/asm-powerpc/mmu-hash64.h b/include/asm-powerpc/mmu-hash64.h new file mode 100644 index 0000000..6739457 --- /dev/null +++ b/include/asm-powerpc/mmu-hash64.h @@ -0,0 +1,400 @@ +#ifndef _ASM_POWERPC_MMU_HASH64_H_ +#define _ASM_POWERPC_MMU_HASH64_H_ +/* + * PowerPC64 memory management structures + * + * Dave Engebretsen & Mike Corrigan <{engebret|mikejc}@us.ibm.com> + * PPC64 rework. + * + * 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 <asm/asm-compat.h> +#include <asm/page.h> + +/* + * Segment table + */ + +#define STE_ESID_V 0x80 +#define STE_ESID_KS 0x20 +#define STE_ESID_KP 0x10 +#define STE_ESID_N 0x08 + +#define STE_VSID_SHIFT 12 + +/* Location of cpu0's segment table */ +#define STAB0_PAGE 0x6 +#define STAB0_OFFSET (STAB0_PAGE << 12) +#define STAB0_PHYS_ADDR (STAB0_OFFSET + PHYSICAL_START) + +#ifndef __ASSEMBLY__ +extern char initial_stab[]; +#endif /* ! __ASSEMBLY */ + +/* + * SLB + */ + +#define SLB_NUM_BOLTED 3 +#define SLB_CACHE_ENTRIES 8 + +/* Bits in the SLB ESID word */ +#define SLB_ESID_V ASM_CONST(0x0000000008000000) /* valid */ + +/* Bits in the SLB VSID word */ +#define SLB_VSID_SHIFT 12 +#define SLB_VSID_B ASM_CONST(0xc000000000000000) +#define SLB_VSID_B_256M ASM_CONST(0x0000000000000000) +#define SLB_VSID_B_1T ASM_CONST(0x4000000000000000) +#define SLB_VSID_KS ASM_CONST(0x0000000000000800) +#define SLB_VSID_KP ASM_CONST(0x0000000000000400) +#define SLB_VSID_N ASM_CONST(0x0000000000000200) /* no-execute */ +#define SLB_VSID_L ASM_CONST(0x0000000000000100) +#define SLB_VSID_C ASM_CONST(0x0000000000000080) /* class */ +#define SLB_VSID_LP ASM_CONST(0x0000000000000030) +#define SLB_VSID_LP_00 ASM_CONST(0x0000000000000000) +#define SLB_VSID_LP_01 ASM_CONST(0x0000000000000010) +#define SLB_VSID_LP_10 ASM_CONST(0x0000000000000020) +#define SLB_VSID_LP_11 ASM_CONST(0x0000000000000030) +#define SLB_VSID_LLP (SLB_VSID_L|SLB_VSID_LP) + +#define SLB_VSID_KERNEL (SLB_VSID_KP) +#define SLB_VSID_USER (SLB_VSID_KP|SLB_VSID_KS|SLB_VSID_C) + +#define SLBIE_C (0x08000000) + +/* + * Hash table + */ + +#define HPTES_PER_GROUP 8 + +#define HPTE_V_AVPN_SHIFT 7 +#define HPTE_V_AVPN ASM_CONST(0xffffffffffffff80) +#define HPTE_V_AVPN_VAL(x) (((x) & HPTE_V_AVPN) >> HPTE_V_AVPN_SHIFT) +#define HPTE_V_COMPARE(x,y) (!(((x) ^ (y)) & HPTE_V_AVPN)) +#define HPTE_V_BOLTED ASM_CONST(0x0000000000000010) +#define HPTE_V_LOCK ASM_CONST(0x0000000000000008) +#define HPTE_V_LARGE ASM_CONST(0x0000000000000004) +#define HPTE_V_SECONDARY ASM_CONST(0x0000000000000002) +#define HPTE_V_VALID ASM_CONST(0x0000000000000001) + +#define HPTE_R_PP0 ASM_CONST(0x8000000000000000) +#define HPTE_R_TS ASM_CONST(0x4000000000000000) +#define HPTE_R_RPN_SHIFT 12 +#define HPTE_R_RPN ASM_CONST(0x3ffffffffffff000) +#define HPTE_R_FLAGS ASM_CONST(0x00000000000003ff) +#define HPTE_R_PP ASM_CONST(0x0000000000000003) +#define HPTE_R_N ASM_CONST(0x0000000000000004) +#define HPTE_R_C ASM_CONST(0x0000000000000080) +#define HPTE_R_R ASM_CONST(0x0000000000000100) + +/* Values for PP (assumes Ks=0, Kp=1) */ +/* pp0 will always be 0 for linux */ +#define PP_RWXX 0 /* Supervisor read/write, User none */ +#define PP_RWRX 1 /* Supervisor read/write, User read */ +#define PP_RWRW 2 /* Supervisor read/write, User read/write */ +#define PP_RXRX 3 /* Supervisor read, User read */ + +#ifndef __ASSEMBLY__ + +typedef struct { + unsigned long v; + unsigned long r; +} hpte_t; + +extern hpte_t *htab_address; +extern unsigned long htab_size_bytes; +extern unsigned long htab_hash_mask; + +/* + * Page size definition + * + * shift : is the "PAGE_SHIFT" value for that page size + * sllp : is a bit mask with the value of SLB L || LP to be or'ed + * directly to a slbmte "vsid" value + * penc : is the HPTE encoding mask for the "LP" field: + * + */ +struct mmu_psize_def +{ + unsigned int shift; /* number of bits */ + unsigned int penc; /* HPTE encoding */ + unsigned int tlbiel; /* tlbiel supported for that page size */ + unsigned long avpnm; /* bits to mask out in AVPN in the HPTE */ + unsigned long sllp; /* SLB L||LP (exact mask to use in slbmte) */ +}; + +#endif /* __ASSEMBLY__ */ + +/* + * The kernel use the constants below to index in the page sizes array. + * The use of fixed constants for this purpose is better for performances + * of the low level hash refill handlers. + * + * A non supported page size has a "shift" field set to 0 + * + * Any new page size being implemented can get a new entry in here. Whether + * the kernel will use it or not is a different matter though. The actual page + * size used by hugetlbfs is not defined here and may be made variable + */ + +#define MMU_PAGE_4K 0 /* 4K */ +#define MMU_PAGE_64K 1 /* 64K */ +#define MMU_PAGE_64K_AP 2 /* 64K Admixed (in a 4K segment) */ +#define MMU_PAGE_1M 3 /* 1M */ +#define MMU_PAGE_16M 4 /* 16M */ +#define MMU_PAGE_16G 5 /* 16G */ +#define MMU_PAGE_COUNT 6 + +#ifndef __ASSEMBLY__ + +/* + * The current system page sizes + */ +extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; +extern int mmu_linear_psize; +extern int mmu_virtual_psize; +extern int mmu_vmalloc_psize; +extern int mmu_io_psize; + +/* + * If the processor supports 64k normal pages but not 64k cache + * inhibited pages, we have to be prepared to switch processes + * to use 4k pages when they create cache-inhibited mappings. + * If this is the case, mmu_ci_restrictions will be set to 1. + */ +extern int mmu_ci_restrictions; + +#ifdef CONFIG_HUGETLB_PAGE +/* + * The page size index of the huge pages for use by hugetlbfs + */ +extern int mmu_huge_psize; + +#endif /* CONFIG_HUGETLB_PAGE */ + +/* + * This function sets the AVPN and L fields of the HPTE appropriately + * for the page size + */ +static inline unsigned long hpte_encode_v(unsigned long va, int psize) +{ + unsigned long v = + v = (va >> 23) & ~(mmu_psize_defs[psize].avpnm); + v <<= HPTE_V_AVPN_SHIFT; + if (psize != MMU_PAGE_4K) + v |= HPTE_V_LARGE; + return v; +} + +/* + * This function sets the ARPN, and LP fields of the HPTE appropriately + * for the page size. We assume the pa is already "clean" that is properly + * aligned for the requested page size + */ +static inline unsigned long hpte_encode_r(unsigned long pa, int psize) +{ + unsigned long r; + + /* A 4K page needs no special encoding */ + if (psize == MMU_PAGE_4K) + return pa & HPTE_R_RPN; + else { + unsigned int penc = mmu_psize_defs[psize].penc; + unsigned int shift = mmu_psize_defs[psize].shift; + return (pa & ~((1ul << shift) - 1)) | (penc << 12); + } + return r; +} + +/* + * This hashes a virtual address for a 256Mb segment only for now + */ + +static inline unsigned long hpt_hash(unsigned long va, unsigned int shift) +{ + return ((va >> 28) & 0x7fffffffffUL) ^ ((va & 0x0fffffffUL) >> shift); +} + +extern int __hash_page_4K(unsigned long ea, unsigned long access, + unsigned long vsid, pte_t *ptep, unsigned long trap, + unsigned int local); +extern int __hash_page_64K(unsigned long ea, unsigned long access, + unsigned long vsid, pte_t *ptep, unsigned long trap, + unsigned int local); +struct mm_struct; +extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap); +extern int hash_huge_page(struct mm_struct *mm, unsigned long access, + unsigned long ea, unsigned long vsid, int local, + unsigned long trap); + +extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend, + unsigned long pstart, unsigned long mode, + int psize); + +extern void htab_initialize(void); +extern void htab_initialize_secondary(void); +extern void hpte_init_native(void); +extern void hpte_init_lpar(void); +extern void hpte_init_iSeries(void); +extern void hpte_init_beat(void); + +extern void stabs_alloc(void); +extern void slb_initialize(void); +extern void slb_flush_and_rebolt(void); +extern void stab_initialize(unsigned long stab); + +#endif /* __ASSEMBLY__ */ + +/* + * VSID allocation + * + * We first generate a 36-bit "proto-VSID". For kernel addresses this + * is equal to the ESID, for user addresses it is: + * (context << 15) | (esid & 0x7fff) + * + * The two forms are distinguishable because the top bit is 0 for user + * addresses, whereas the top two bits are 1 for kernel addresses. + * Proto-VSIDs with the top two bits equal to 0b10 are reserved for + * now. + * + * The proto-VSIDs are then scrambled into real VSIDs with the + * multiplicative hash: + * + * VSID = (proto-VSID * VSID_MULTIPLIER) % VSID_MODULUS + * where VSID_MULTIPLIER = 268435399 = 0xFFFFFC7 + * VSID_MODULUS = 2^36-1 = 0xFFFFFFFFF + * + * This scramble is only well defined for proto-VSIDs below + * 0xFFFFFFFFF, so both proto-VSID and actual VSID 0xFFFFFFFFF are + * reserved. VSID_MULTIPLIER is prime, so in particular it is + * co-prime to VSID_MODULUS, making this a 1:1 scrambling function. + * Because the modulus is 2^n-1 we can compute it efficiently without + * a divide or extra multiply (see below). + * + * This scheme has several advantages over older methods: + * + * - We have VSIDs allocated for every kernel address + * (i.e. everything above 0xC000000000000000), except the very top + * segment, which simplifies several things. + * + * - We allow for 15 significant bits of ESID and 20 bits of + * context for user addresses. i.e. 8T (43 bits) of address space for + * up to 1M contexts (although the page table structure and context + * allocation will need changes to take advantage of this). + * + * - The scramble function gives robust scattering in the hash + * table (at least based on some initial results). The previous + * method was more susceptible to pathological cases giving excessive + * hash collisions. + */ +/* + * WARNING - If you change these you must make sure the asm + * implementations in slb_allocate (slb_low.S), do_stab_bolted + * (head.S) and ASM_VSID_SCRAMBLE (below) are changed accordingly. + * + * You'll also need to change the precomputed VSID values in head.S + * which are used by the iSeries firmware. + */ + +#define VSID_MULTIPLIER ASM_CONST(200730139) /* 28-bit prime */ +#define VSID_BITS 36 +#define VSID_MODULUS ((1UL<<VSID_BITS)-1) + +#define CONTEXT_BITS 19 +#define USER_ESID_BITS 16 + +#define USER_VSID_RANGE (1UL << (USER_ESID_BITS + SID_SHIFT)) + +/* + * This macro generates asm code to compute the VSID scramble + * function. Used in slb_allocate() and do_stab_bolted. The function + * computed is: (protovsid*VSID_MULTIPLIER) % VSID_MODULUS + * + * rt = register continaing the proto-VSID and into which the + * VSID will be stored + * rx = scratch register (clobbered) + * + * - rt and rx must be different registers + * - The answer will end up in the low 36 bits of rt. The higher + * bits may contain other garbage, so you may need to mask the + * result. + */ +#define ASM_VSID_SCRAMBLE(rt, rx) \ + lis rx,VSID_MULTIPLIER@h; \ + ori rx,rx,VSID_MULTIPLIER@l; \ + mulld rt,rt,rx; /* rt = rt * MULTIPLIER */ \ + \ + srdi rx,rt,VSID_BITS; \ + clrldi rt,rt,(64-VSID_BITS); \ + add rt,rt,rx; /* add high and low bits */ \ + /* Now, r3 == VSID (mod 2^36-1), and lies between 0 and \ + * 2^36-1+2^28-1. That in particular means that if r3 >= \ + * 2^36-1, then r3+1 has the 2^36 bit set. So, if r3+1 has \ + * the bit clear, r3 already has the answer we want, if it \ + * doesn't, the answer is the low 36 bits of r3+1. So in all \ + * cases the answer is the low 36 bits of (r3 + ((r3+1) >> 36))*/\ + addi rx,rt,1; \ + srdi rx,rx,VSID_BITS; /* extract 2^36 bit */ \ + add rt,rt,rx + + +#ifndef __ASSEMBLY__ + +typedef unsigned long mm_context_id_t; + +typedef struct { + mm_context_id_t id; + u16 user_psize; /* page size index */ + u16 sllp; /* SLB entry page size encoding */ +#ifdef CONFIG_HUGETLB_PAGE + u16 low_htlb_areas, high_htlb_areas; +#endif + unsigned long vdso_base; +} mm_context_t; + + +static inline unsigned long vsid_scramble(unsigned long protovsid) +{ +#if 0 + /* The code below is equivalent to this function for arguments + * < 2^VSID_BITS, which is all this should ever be called + * with. However gcc is not clever enough to compute the + * modulus (2^n-1) without a second multiply. */ + return ((protovsid * VSID_MULTIPLIER) % VSID_MODULUS); +#else /* 1 */ + unsigned long x; + + x = protovsid * VSID_MULTIPLIER; + x = (x >> VSID_BITS) + (x & VSID_MODULUS); + return (x + ((x+1) >> VSID_BITS)) & VSID_MODULUS; +#endif /* 1 */ +} + +/* This is only valid for addresses >= KERNELBASE */ +static inline unsigned long get_kernel_vsid(unsigned long ea) +{ + return vsid_scramble(ea >> SID_SHIFT); +} + +/* This is only valid for user addresses (which are below 2^41) */ +static inline unsigned long get_vsid(unsigned long context, unsigned long ea) +{ + return vsid_scramble((context << USER_ESID_BITS) + | (ea >> SID_SHIFT)); +} + +#define VSID_SCRAMBLE(pvsid) (((pvsid) * VSID_MULTIPLIER) % VSID_MODULUS) +#define KERNEL_VSID(ea) VSID_SCRAMBLE(GET_ESID(ea)) + +/* Physical address used by some IO functions */ +typedef unsigned long phys_addr_t; + +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_POWERPC_MMU_HASH64_H_ */ diff --git a/include/asm-powerpc/mmu.h b/include/asm-powerpc/mmu.h index 200055a..06b3e6d 100644 --- a/include/asm-powerpc/mmu.h +++ b/include/asm-powerpc/mmu.h @@ -2,407 +2,14 @@ #define _ASM_POWERPC_MMU_H_ #ifdef __KERNEL__ -#ifndef CONFIG_PPC64 -#include <asm-ppc/mmu.h> +#ifdef CONFIG_PPC64 +/* 64-bit classic hash table MMU */ +# include <asm/mmu-hash64.h> #else - -/* - * PowerPC memory management structures - * - * Dave Engebretsen & Mike Corrigan <{engebret|mikejc}@us.ibm.com> - * PPC64 rework. - * - * 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 <asm/asm-compat.h> -#include <asm/page.h> - -/* - * Segment table - */ - -#define STE_ESID_V 0x80 -#define STE_ESID_KS 0x20 -#define STE_ESID_KP 0x10 -#define STE_ESID_N 0x08 - -#define STE_VSID_SHIFT 12 - -/* Location of cpu0's segment table */ -#define STAB0_PAGE 0x6 -#define STAB0_OFFSET (STAB0_PAGE << 12) -#define STAB0_PHYS_ADDR (STAB0_OFFSET + PHYSICAL_START) - -#ifndef __ASSEMBLY__ -extern char initial_stab[]; -#endif /* ! __ASSEMBLY */ - -/* - * SLB - */ - -#define SLB_NUM_BOLTED 3 -#define SLB_CACHE_ENTRIES 8 - -/* Bits in the SLB ESID word */ -#define SLB_ESID_V ASM_CONST(0x0000000008000000) /* valid */ - -/* Bits in the SLB VSID word */ -#define SLB_VSID_SHIFT 12 -#define SLB_VSID_B ASM_CONST(0xc000000000000000) -#define SLB_VSID_B_256M ASM_CONST(0x0000000000000000) -#define SLB_VSID_B_1T ASM_CONST(0x4000000000000000) -#define SLB_VSID_KS ASM_CONST(0x0000000000000800) -#define SLB_VSID_KP ASM_CONST(0x0000000000000400) -#define SLB_VSID_N ASM_CONST(0x0000000000000200) /* no-execute */ -#define SLB_VSID_L ASM_CONST(0x0000000000000100) -#define SLB_VSID_C ASM_CONST(0x0000000000000080) /* class */ -#define SLB_VSID_LP ASM_CONST(0x0000000000000030) -#define SLB_VSID_LP_00 ASM_CONST(0x0000000000000000) -#define SLB_VSID_LP_01 ASM_CONST(0x0000000000000010) -#define SLB_VSID_LP_10 ASM_CONST(0x0000000000000020) -#define SLB_VSID_LP_11 ASM_CONST(0x0000000000000030) -#define SLB_VSID_LLP (SLB_VSID_L|SLB_VSID_LP) - -#define SLB_VSID_KERNEL (SLB_VSID_KP) -#define SLB_VSID_USER (SLB_VSID_KP|SLB_VSID_KS|SLB_VSID_C) - -#define SLBIE_C (0x08000000) - -/* - * Hash table - */ - -#define HPTES_PER_GROUP 8 - -#define HPTE_V_AVPN_SHIFT 7 -#define HPTE_V_AVPN ASM_CONST(0xffffffffffffff80) -#define HPTE_V_AVPN_VAL(x) (((x) & HPTE_V_AVPN) >> HPTE_V_AVPN_SHIFT) -#define HPTE_V_COMPARE(x,y) (!(((x) ^ (y)) & HPTE_V_AVPN)) -#define HPTE_V_BOLTED ASM_CONST(0x0000000000000010) -#define HPTE_V_LOCK ASM_CONST(0x0000000000000008) -#define HPTE_V_LARGE ASM_CONST(0x0000000000000004) -#define HPTE_V_SECONDARY ASM_CONST(0x0000000000000002) -#define HPTE_V_VALID ASM_CONST(0x0000000000000001) - -#define HPTE_R_PP0 ASM_CONST(0x8000000000000000) -#define HPTE_R_TS ASM_CONST(0x4000000000000000) -#define HPTE_R_RPN_SHIFT 12 -#define HPTE_R_RPN ASM_CONST(0x3ffffffffffff000) -#define HPTE_R_FLAGS ASM_CONST(0x00000000000003ff) -#define HPTE_R_PP ASM_CONST(0x0000000000000003) -#define HPTE_R_N ASM_CONST(0x0000000000000004) -#define HPTE_R_C ASM_CONST(0x0000000000000080) -#define HPTE_R_R ASM_CONST(0x0000000000000100) - -/* Values for PP (assumes Ks=0, Kp=1) */ -/* pp0 will always be 0 for linux */ -#define PP_RWXX 0 /* Supervisor read/write, User none */ -#define PP_RWRX 1 /* Supervisor read/write, User read */ -#define PP_RWRW 2 /* Supervisor read/write, User read/write */ -#define PP_RXRX 3 /* Supervisor read, User read */ - -#ifndef __ASSEMBLY__ - -typedef struct { - unsigned long v; - unsigned long r; -} hpte_t; - -extern hpte_t *htab_address; -extern unsigned long htab_size_bytes; -extern unsigned long htab_hash_mask; - -/* - * Page size definition - * - * shift : is the "PAGE_SHIFT" value for that page size - * sllp : is a bit mask with the value of SLB L || LP to be or'ed - * directly to a slbmte "vsid" value - * penc : is the HPTE encoding mask for the "LP" field: - * - */ -struct mmu_psize_def -{ - unsigned int shift; /* number of bits */ - unsigned int penc; /* HPTE encoding */ - unsigned int tlbiel; /* tlbiel supported for that page size */ - unsigned long avpnm; /* bits to mask out in AVPN in the HPTE */ - unsigned long sllp; /* SLB L||LP (exact mask to use in slbmte) */ -}; - -#endif /* __ASSEMBLY__ */ - -/* - * The kernel use the constants below to index in the page sizes array. - * The use of fixed constants for this purpose is better for performances - * of the low level hash refill handlers. - * - * A non supported page size has a "shift" field set to 0 - * - * Any new page size being implemented can get a new entry in here. Whether - * the kernel will use it or not is a different matter though. The actual page - * size used by hugetlbfs is not defined here and may be made variable - */ - -#define MMU_PAGE_4K 0 /* 4K */ -#define MMU_PAGE_64K 1 /* 64K */ -#define MMU_PAGE_64K_AP 2 /* 64K Admixed (in a 4K segment) */ -#define MMU_PAGE_1M 3 /* 1M */ -#define MMU_PAGE_16M 4 /* 16M */ -#define MMU_PAGE_16G 5 /* 16G */ -#define MMU_PAGE_COUNT 6 - -#ifndef __ASSEMBLY__ - -/* - * The current system page sizes - */ -extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; -extern int mmu_linear_psize; -extern int mmu_virtual_psize; -extern int mmu_vmalloc_psize; -extern int mmu_io_psize; - -/* - * If the processor supports 64k normal pages but not 64k cache - * inhibited pages, we have to be prepared to switch processes - * to use 4k pages when they create cache-inhibited mappings. - * If this is the case, mmu_ci_restrictions will be set to 1. - */ -extern int mmu_ci_restrictions; - -#ifdef CONFIG_HUGETLB_PAGE -/* - * The page size index of the huge pages for use by hugetlbfs - */ -extern int mmu_huge_psize; - -#endif /* CONFIG_HUGETLB_PAGE */ - -/* - * This function sets the AVPN and L fields of the HPTE appropriately - * for the page size - */ -static inline unsigned long hpte_encode_v(unsigned long va, int psize) -{ - unsigned long v = - v = (va >> 23) & ~(mmu_psize_defs[psize].avpnm); - v <<= HPTE_V_AVPN_SHIFT; - if (psize != MMU_PAGE_4K) - v |= HPTE_V_LARGE; - return v; -} - -/* - * This function sets the ARPN, and LP fields of the HPTE appropriately - * for the page size. We assume the pa is already "clean" that is properly - * aligned for the requested page size - */ -static inline unsigned long hpte_encode_r(unsigned long pa, int psize) -{ - unsigned long r; - - /* A 4K page needs no special encoding */ - if (psize == MMU_PAGE_4K) - return pa & HPTE_R_RPN; - else { - unsigned int penc = mmu_psize_defs[psize].penc; - unsigned int shift = mmu_psize_defs[psize].shift; - return (pa & ~((1ul << shift) - 1)) | (penc << 12); - } - return r; -} - -/* - * This hashes a virtual address for a 256Mb segment only for now - */ - -static inline unsigned long hpt_hash(unsigned long va, unsigned int shift) -{ - return ((va >> 28) & 0x7fffffffffUL) ^ ((va & 0x0fffffffUL) >> shift); -} - -extern int __hash_page_4K(unsigned long ea, unsigned long access, - unsigned long vsid, pte_t *ptep, unsigned long trap, - unsigned int local); -extern int __hash_page_64K(unsigned long ea, unsigned long access, - unsigned long vsid, pte_t *ptep, unsigned long trap, - unsigned int local); -struct mm_struct; -extern int hash_huge_page(struct mm_struct *mm, unsigned long access, - unsigned long ea, unsigned long vsid, int local, - unsigned long trap); - -extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend, - unsigned long pstart, unsigned long mode, - int psize); - -extern void htab_initialize(void); -extern void htab_initialize_secondary(void); -extern void hpte_init_native(void); -extern void hpte_init_lpar(void); -extern void hpte_init_iSeries(void); -extern void hpte_init_beat(void); - -extern void stabs_alloc(void); -extern void slb_initialize(void); -extern void slb_flush_and_rebolt(void); -extern void stab_initialize(unsigned long stab); - -#endif /* __ASSEMBLY__ */ - -/* - * VSID allocation - * - * We first generate a 36-bit "proto-VSID". For kernel addresses this - * is equal to the ESID, for user addresses it is: - * (context << 15) | (esid & 0x7fff) - * - * The two forms are distinguishable because the top bit is 0 for user - * addresses, whereas the top two bits are 1 for kernel addresses. - * Proto-VSIDs with the top two bits equal to 0b10 are reserved for - * now. - * - * The proto-VSIDs are then scrambled into real VSIDs with the - * multiplicative hash: - * - * VSID = (proto-VSID * VSID_MULTIPLIER) % VSID_MODULUS - * where VSID_MULTIPLIER = 268435399 = 0xFFFFFC7 - * VSID_MODULUS = 2^36-1 = 0xFFFFFFFFF - * - * This scramble is only well defined for proto-VSIDs below - * 0xFFFFFFFFF, so both proto-VSID and actual VSID 0xFFFFFFFFF are - * reserved. VSID_MULTIPLIER is prime, so in particular it is - * co-prime to VSID_MODULUS, making this a 1:1 scrambling function. - * Because the modulus is 2^n-1 we can compute it efficiently without - * a divide or extra multiply (see below). - * - * This scheme has several advantages over older methods: - * - * - We have VSIDs allocated for every kernel address - * (i.e. everything above 0xC000000000000000), except the very top - * segment, which simplifies several things. - * - * - We allow for 15 significant bits of ESID and 20 bits of - * context for user addresses. i.e. 8T (43 bits) of address space for - * up to 1M contexts (although the page table structure and context - * allocation will need changes to take advantage of this). - * - * - The scramble function gives robust scattering in the hash - * table (at least based on some initial results). The previous - * method was more susceptible to pathological cases giving excessive - * hash collisions. - */ -/* - * WARNING - If you change these you must make sure the asm - * implementations in slb_allocate (slb_low.S), do_stab_bolted - * (head.S) and ASM_VSID_SCRAMBLE (below) are changed accordingly. - * - * You'll also need to change the precomputed VSID values in head.S - * which are used by the iSeries firmware. - */ - -#define VSID_MULTIPLIER ASM_CONST(200730139) /* 28-bit prime */ -#define VSID_BITS 36 -#define VSID_MODULUS ((1UL<<VSID_BITS)-1) - -#define CONTEXT_BITS 19 -#define USER_ESID_BITS 16 - -#define USER_VSID_RANGE (1UL << (USER_ESID_BITS + SID_SHIFT)) - -/* - * This macro generates asm code to compute the VSID scramble - * function. Used in slb_allocate() and do_stab_bolted. The function - * computed is: (protovsid*VSID_MULTIPLIER) % VSID_MODULUS - * - * rt = register continaing the proto-VSID and into which the - * VSID will be stored - * rx = scratch register (clobbered) - * - * - rt and rx must be different registers - * - The answer will end up in the low 36 bits of rt. The higher - * bits may contain other garbage, so you may need to mask the - * result. - */ -#define ASM_VSID_SCRAMBLE(rt, rx) \ - lis rx,VSID_MULTIPLIER@h; \ - ori rx,rx,VSID_MULTIPLIER@l; \ - mulld rt,rt,rx; /* rt = rt * MULTIPLIER */ \ - \ - srdi rx,rt,VSID_BITS; \ - clrldi rt,rt,(64-VSID_BITS); \ - add rt,rt,rx; /* add high and low bits */ \ - /* Now, r3 == VSID (mod 2^36-1), and lies between 0 and \ - * 2^36-1+2^28-1. That in particular means that if r3 >= \ - * 2^36-1, then r3+1 has the 2^36 bit set. So, if r3+1 has \ - * the bit clear, r3 already has the answer we want, if it \ - * doesn't, the answer is the low 36 bits of r3+1. So in all \ - * cases the answer is the low 36 bits of (r3 + ((r3+1) >> 36))*/\ - addi rx,rt,1; \ - srdi rx,rx,VSID_BITS; /* extract 2^36 bit */ \ - add rt,rt,rx - - -#ifndef __ASSEMBLY__ - -typedef unsigned long mm_context_id_t; - -typedef struct { - mm_context_id_t id; - u16 user_psize; /* page size index */ - u16 sllp; /* SLB entry page size encoding */ -#ifdef CONFIG_HUGETLB_PAGE - u16 low_htlb_areas, high_htlb_areas; +/* 32-bit. FIXME: split up the 32-bit MMU types, and revise for + * arch/powerpc */ +# include <asm-ppc/mmu.h> #endif - unsigned long vdso_base; -} mm_context_t; - - -static inline unsigned long vsid_scramble(unsigned long protovsid) -{ -#if 0 - /* The code below is equivalent to this function for arguments - * < 2^VSID_BITS, which is all this should ever be called - * with. However gcc is not clever enough to compute the - * modulus (2^n-1) without a second multiply. */ - return ((protovsid * VSID_MULTIPLIER) % VSID_MODULUS); -#else /* 1 */ - unsigned long x; - - x = protovsid * VSID_MULTIPLIER; - x = (x >> VSID_BITS) + (x & VSID_MODULUS); - return (x + ((x+1) >> VSID_BITS)) & VSID_MODULUS; -#endif /* 1 */ -} - -/* This is only valid for addresses >= KERNELBASE */ -static inline unsigned long get_kernel_vsid(unsigned long ea) -{ - return vsid_scramble(ea >> SID_SHIFT); -} - -/* This is only valid for user addresses (which are below 2^41) */ -static inline unsigned long get_vsid(unsigned long context, unsigned long ea) -{ - return vsid_scramble((context << USER_ESID_BITS) - | (ea >> SID_SHIFT)); -} - -#define VSID_SCRAMBLE(pvsid) (((pvsid) * VSID_MULTIPLIER) % VSID_MODULUS) -#define KERNEL_VSID(ea) VSID_SCRAMBLE(GET_ESID(ea)) - -/* Physical address used by some IO functions */ -typedef unsigned long phys_addr_t; - - -#endif /* __ASSEMBLY */ -#endif /* CONFIG_PPC64 */ #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_MMU_H_ */ diff --git a/include/asm-powerpc/mpic.h b/include/asm-powerpc/mpic.h index cb204a7..e4d5fc5 100644 --- a/include/asm-powerpc/mpic.h +++ b/include/asm-powerpc/mpic.h @@ -199,7 +199,7 @@ enum { }; -#ifdef CONFIG_MPIC_BROKEN_U3 +#ifdef CONFIG_MPIC_U3_HT_IRQS /* Fixup table entry */ struct mpic_irq_fixup { @@ -208,7 +208,7 @@ struct mpic_irq_fixup u32 data; unsigned int index; }; -#endif /* CONFIG_MPIC_BROKEN_U3 */ +#endif /* CONFIG_MPIC_U3_HT_IRQS */ enum mpic_reg_type { @@ -239,7 +239,7 @@ struct mpic /* The "linux" controller struct */ struct irq_chip hc_irq; -#ifdef CONFIG_MPIC_BROKEN_U3 +#ifdef CONFIG_MPIC_U3_HT_IRQS struct irq_chip hc_ht_irq; #endif #ifdef CONFIG_SMP @@ -268,7 +268,7 @@ struct mpic /* Spurious vector to program into unused sources */ unsigned int spurious_vec; -#ifdef CONFIG_MPIC_BROKEN_U3 +#ifdef CONFIG_MPIC_U3_HT_IRQS /* The fixup table */ struct mpic_irq_fixup *fixups; spinlock_t fixup_lock; @@ -313,7 +313,7 @@ struct mpic /* Set this for a big-endian MPIC */ #define MPIC_BIG_ENDIAN 0x00000002 /* Broken U3 MPIC */ -#define MPIC_BROKEN_U3 0x00000004 +#define MPIC_U3_HT_IRQS 0x00000004 /* Broken IPI registers (autodetected) */ #define MPIC_BROKEN_IPI 0x00000008 /* MPIC wants a reset */ @@ -352,7 +352,7 @@ struct mpic * @senses_num: number of entries in the array * * Note about the sense array. If none is passed, all interrupts are - * setup to be level negative unless MPIC_BROKEN_U3 is set in which + * setup to be level negative unless MPIC_U3_HT_IRQS is set in which * case they are edge positive (and the array is ignored anyway). * The values in the array start at the first source of the MPIC, * that is senses[0] correspond to linux irq "irq_offset". diff --git a/include/asm-powerpc/of_device.h b/include/asm-powerpc/of_device.h index a889b20..4f1aabe 100644 --- a/include/asm-powerpc/of_device.h +++ b/include/asm-powerpc/of_device.h @@ -32,5 +32,8 @@ extern int of_device_register(struct of_device *ofdev); extern void of_device_unregister(struct of_device *ofdev); extern void of_release_dev(struct device *dev); +extern int of_device_uevent(struct device *dev, + char **envp, int num_envp, char *buffer, int buffer_size); + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_OF_DEVICE_H */ diff --git a/include/asm-powerpc/oprofile_impl.h b/include/asm-powerpc/oprofile_impl.h index 94c0ad2..8d6b47f 100644 --- a/include/asm-powerpc/oprofile_impl.h +++ b/include/asm-powerpc/oprofile_impl.h @@ -57,6 +57,8 @@ extern struct op_powerpc_model op_model_rs64; extern struct op_powerpc_model op_model_power4; extern struct op_powerpc_model op_model_7450; extern struct op_powerpc_model op_model_cell; +extern struct op_powerpc_model op_model_pa6t; + /* All the classic PPC parts use these */ static inline unsigned int classic_ctr_read(unsigned int i) diff --git a/include/asm-powerpc/paca.h b/include/asm-powerpc/paca.h index 0d3adc0..cf95274 100644 --- a/include/asm-powerpc/paca.h +++ b/include/asm-powerpc/paca.h @@ -70,6 +70,7 @@ struct paca_struct { s16 hw_cpu_id; /* Physical processor number */ u8 cpu_start; /* At startup, processor spins until */ /* this becomes non-zero. */ + struct slb_shadow *slb_shadow_ptr; /* * Now, starting in cacheline 2, the exception save areas @@ -93,6 +94,7 @@ struct paca_struct { u64 stab_rr; /* stab/slb round-robin counter */ u64 saved_r1; /* r1 save for RTAS calls */ u64 saved_msr; /* MSR saved here by enter_rtas */ + u16 trap_save; /* Used when bad stack is encountered */ u8 soft_enabled; /* irq soft-enable flag */ u8 hard_enabled; /* set if irqs are enabled in MSR */ u8 io_sync; /* writel() needs spin_unlock sync */ @@ -101,8 +103,6 @@ struct paca_struct { u64 user_time; /* accumulated usermode TB ticks */ u64 system_time; /* accumulated system TB ticks */ u64 startpurr; /* PURR/TB value snapshot */ - - struct slb_shadow *slb_shadow_ptr; }; extern struct paca_struct paca[]; diff --git a/include/asm-powerpc/parport.h b/include/asm-powerpc/parport.h index 3fca21d..b37b81e 100644 --- a/include/asm-powerpc/parport.h +++ b/include/asm-powerpc/parport.h @@ -20,18 +20,18 @@ extern struct parport *parport_pc_probe_port (unsigned long int base, static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma) { struct device_node *np; - u32 *prop; + const u32 *prop; u32 io1, io2; int propsize; int count = 0; for (np = NULL; (np = of_find_compatible_node(np, "parallel", "pnpPNP,400")) != NULL;) { - prop = (u32 *)get_property(np, "reg", &propsize); + prop = of_get_property(np, "reg", &propsize); if (!prop || propsize > 6*sizeof(u32)) continue; io1 = prop[1]; io2 = prop[2]; - prop = (u32 *)get_property(np, "interrupts", NULL); + prop = of_get_property(np, "interrupts", NULL); if (!prop) continue; if (parport_pc_probe_port(io1, io2, prop[0], autodma, NULL) != NULL) diff --git a/include/asm-powerpc/pci.h b/include/asm-powerpc/pci.h index ac656ee..ce0f13e 100644 --- a/include/asm-powerpc/pci.h +++ b/include/asm-powerpc/pci.h @@ -70,19 +70,22 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) */ #define PCI_DISABLE_MWI -extern struct dma_mapping_ops *pci_dma_ops; +#ifdef CONFIG_PCI +extern void set_pci_dma_ops(struct dma_mapping_ops *dma_ops); +extern struct dma_mapping_ops *get_pci_dma_ops(void); /* For DAC DMA, we currently don't support it by default, but * we let 64-bit platforms override this. */ static inline int pci_dac_dma_supported(struct pci_dev *hwdev,u64 mask) { - if (pci_dma_ops && pci_dma_ops->dac_dma_supported) - return pci_dma_ops->dac_dma_supported(&hwdev->dev, mask); + struct dma_mapping_ops *d = get_pci_dma_ops(); + + if (d && d->dac_dma_supported) + return d->dac_dma_supported(&hwdev->dev, mask); return 0; } -#ifdef CONFIG_PCI static inline void pci_dma_burst_advice(struct pci_dev *pdev, enum pci_dma_burst_strategy *strat, unsigned long *strategy_parameter) @@ -99,6 +102,9 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev, *strat = PCI_DMA_BURST_MULTIPLE; *strategy_parameter = cacheline_size; } +#else /* CONFIG_PCI */ +#define set_pci_dma_ops(d) +#define get_pci_dma_ops() NULL #endif extern int pci_domain_nr(struct pci_bus *bus); diff --git a/include/asm-powerpc/pgtable-4k.h b/include/asm-powerpc/pgtable-4k.h index 345d9b0..a28fa8b 100644 --- a/include/asm-powerpc/pgtable-4k.h +++ b/include/asm-powerpc/pgtable-4k.h @@ -97,3 +97,6 @@ #define pud_ERROR(e) \ printk("%s:%d: bad pud %08lx.\n", __FILE__, __LINE__, pud_val(e)) + +#define remap_4k_pfn(vma, addr, pfn, prot) \ + remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE, (prot)) diff --git a/include/asm-powerpc/pgtable-64k.h b/include/asm-powerpc/pgtable-64k.h index 4b7126c..5e84f07 100644 --- a/include/asm-powerpc/pgtable-64k.h +++ b/include/asm-powerpc/pgtable-64k.h @@ -35,6 +35,7 @@ #define _PAGE_HPTE_SUB 0x0ffff000 /* combo only: sub pages HPTE bits */ #define _PAGE_HPTE_SUB0 0x08000000 /* combo only: first sub page */ #define _PAGE_COMBO 0x10000000 /* this is a combo 4k page */ +#define _PAGE_4K_PFN 0x20000000 /* PFN is for a single 4k page */ #define _PAGE_F_SECOND 0x00008000 /* full page: hidx bits */ #define _PAGE_F_GIX 0x00007000 /* full page: hidx bits */ @@ -93,6 +94,10 @@ #define pte_pagesize_index(pte) \ (((pte) & _PAGE_COMBO)? MMU_PAGE_4K: MMU_PAGE_64K) +#define remap_4k_pfn(vma, addr, pfn, prot) \ + remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE, \ + __pgprot(pgprot_val((prot)) | _PAGE_4K_PFN)) + #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_PGTABLE_64K_H */ diff --git a/include/asm-powerpc/pgtable.h b/include/asm-powerpc/pgtable.h index 10f52743f..19edb69 100644 --- a/include/asm-powerpc/pgtable.h +++ b/include/asm-powerpc/pgtable.h @@ -272,7 +272,10 @@ static inline pte_t pte_mkhuge(pte_t pte) { return pte; } /* Atomic PTE updates */ -static inline unsigned long pte_update(pte_t *p, unsigned long clr) +static inline unsigned long pte_update(struct mm_struct *mm, + unsigned long addr, + pte_t *ptep, unsigned long clr, + int huge) { unsigned long old, tmp; @@ -283,20 +286,15 @@ static inline unsigned long pte_update(pte_t *p, unsigned long clr) andc %1,%0,%4 \n\ stdcx. %1,0,%3 \n\ bne- 1b" - : "=&r" (old), "=&r" (tmp), "=m" (*p) - : "r" (p), "r" (clr), "m" (*p), "i" (_PAGE_BUSY) + : "=&r" (old), "=&r" (tmp), "=m" (*ptep) + : "r" (ptep), "r" (clr), "m" (*ptep), "i" (_PAGE_BUSY) : "cc" ); + + if (old & _PAGE_HASHPTE) + hpte_need_flush(mm, addr, ptep, old, huge); return old; } -/* PTE updating functions, this function puts the PTE in the - * batch, doesn't actually triggers the hash flush immediately, - * you need to call flush_tlb_pending() to do that. - * Pass -1 for "normal" size (4K or 64K) - */ -extern void hpte_update(struct mm_struct *mm, unsigned long addr, - pte_t *ptep, unsigned long pte, int huge); - static inline int __ptep_test_and_clear_young(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { @@ -304,11 +302,7 @@ static inline int __ptep_test_and_clear_young(struct mm_struct *mm, if ((pte_val(*ptep) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0) return 0; - old = pte_update(ptep, _PAGE_ACCESSED); - if (old & _PAGE_HASHPTE) { - hpte_update(mm, addr, ptep, old, 0); - flush_tlb_pending(); - } + old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0); return (old & _PAGE_ACCESSED) != 0; } #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG @@ -331,9 +325,7 @@ static inline int __ptep_test_and_clear_dirty(struct mm_struct *mm, if ((pte_val(*ptep) & _PAGE_DIRTY) == 0) return 0; - old = pte_update(ptep, _PAGE_DIRTY); - if (old & _PAGE_HASHPTE) - hpte_update(mm, addr, ptep, old, 0); + old = pte_update(mm, addr, ptep, _PAGE_DIRTY, 0); return (old & _PAGE_DIRTY) != 0; } #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY @@ -352,9 +344,7 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, if ((pte_val(*ptep) & _PAGE_RW) == 0) return; - old = pte_update(ptep, _PAGE_RW); - if (old & _PAGE_HASHPTE) - hpte_update(mm, addr, ptep, old, 0); + old = pte_update(mm, addr, ptep, _PAGE_RW, 0); } /* @@ -378,7 +368,6 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, ({ \ int __dirty = __ptep_test_and_clear_dirty((__vma)->vm_mm, __address, \ __ptep); \ - flush_tlb_page(__vma, __address); \ __dirty; \ }) @@ -386,20 +375,14 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { - unsigned long old = pte_update(ptep, ~0UL); - - if (old & _PAGE_HASHPTE) - hpte_update(mm, addr, ptep, old, 0); + unsigned long old = pte_update(mm, addr, ptep, ~0UL, 0); return __pte(old); } static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t * ptep) { - unsigned long old = pte_update(ptep, ~0UL); - - if (old & _PAGE_HASHPTE) - hpte_update(mm, addr, ptep, old, 0); + pte_update(mm, addr, ptep, ~0UL, 0); } /* @@ -408,10 +391,8 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte) { - if (pte_present(*ptep)) { + if (pte_present(*ptep)) pte_clear(mm, addr, ptep); - flush_tlb_pending(); - } pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS); *ptep = pte; } @@ -467,16 +448,6 @@ extern pgd_t swapper_pg_dir[]; extern void paging_init(void); -/* - * This gets called at the end of handling a page fault, when - * the kernel has put a new PTE into the page table for the process. - * We use it to put a corresponding HPTE into the hash table - * ahead of time, instead of waiting for the inevitable extra - * hash-table miss exception. - */ -struct vm_area_struct; -extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); - /* Encode and de-code a swap entry */ #define __swp_type(entry) (((entry).val >> 1) & 0x3f) #define __swp_offset(entry) ((entry).val >> 8) @@ -522,6 +493,7 @@ void pgtable_cache_init(void); return pt; } + #include <asm-generic/pgtable.h> #endif /* __ASSEMBLY__ */ diff --git a/include/asm-powerpc/pmc.h b/include/asm-powerpc/pmc.h index 8588be6..d6a616a 100644 --- a/include/asm-powerpc/pmc.h +++ b/include/asm-powerpc/pmc.h @@ -30,6 +30,7 @@ void release_pmc_hardware(void); #ifdef CONFIG_PPC64 void power4_enable_pmcs(void); +void pasemi_enable_pmcs(void); #endif #endif /* __KERNEL__ */ diff --git a/include/asm-powerpc/ppc-pci.h b/include/asm-powerpc/ppc-pci.h index ab6eddb..d74b296 100644 --- a/include/asm-powerpc/ppc-pci.h +++ b/include/asm-powerpc/ppc-pci.h @@ -10,6 +10,8 @@ #define _ASM_POWERPC_PPC_PCI_H #ifdef __KERNEL__ +#ifdef CONFIG_PCI + #include <linux/pci.h> #include <asm/pci-bridge.h> @@ -22,7 +24,7 @@ extern void pci_setup_phb_io_dynamic(struct pci_controller *hose, int primary); extern struct list_head hose_list; extern int global_phb_number; -extern unsigned long find_and_init_phbs(void); +extern void find_and_init_phbs(void); extern struct pci_dev *ppc64_isabridge_dev; /* may be NULL if no ISA bus */ @@ -68,7 +70,7 @@ struct pci_dev *pci_get_device_by_addr(unsigned long addr); void eeh_slot_error_detail (struct pci_dn *pdn, int severity); /** - * rtas_pci_enableo - enable IO transfers for this slot + * rtas_pci_enable - enable IO transfers for this slot * @pdn: pci device node * @function: either EEH_THAW_MMIO or EEH_THAW_DMA * @@ -89,6 +91,7 @@ int rtas_pci_enable(struct pci_dn *pdn, int function); * Returns a non-zero value if the reset failed. */ int rtas_set_slot_reset (struct pci_dn *); +int eeh_wait_for_slot_status(struct pci_dn *pdn, int max_wait_msecs); /** * eeh_restore_bars - Restore device configuration info. @@ -126,5 +129,10 @@ struct device_node * find_device_pe(struct device_node *dn); #endif +#else /* CONFIG_PCI */ +static inline void find_and_init_phbs(void) { } +static inline void init_pci_config_tokens(void) { } +#endif /* !CONFIG_PCI */ + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_PPC_PCI_H */ diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h index a26c32e..d947b16 100644 --- a/include/asm-powerpc/processor.h +++ b/include/asm-powerpc/processor.h @@ -133,7 +133,6 @@ struct thread_struct { mm_segment_t fs; /* for get_fs() validation */ #ifdef CONFIG_PPC32 void *pgdir; /* root of page-table tree */ - signed long last_syscall; #endif #if defined(CONFIG_4xx) || defined (CONFIG_BOOKE) unsigned long dbcr0; /* debug control register values */ diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 020ed01..ec400f6 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -18,7 +18,9 @@ #include <linux/types.h> #include <linux/proc_fs.h> #include <linux/platform_device.h> +#include <asm/irq.h> #include <asm/atomic.h> +#include <asm/io.h> /* Definitions used by the flattened device tree */ #define OF_DT_HEADER 0xd00dfeed /* marker */ @@ -58,6 +60,8 @@ struct boot_param_header u32 boot_cpuid_phys; /* Physical CPU id we're booting on */ /* version 3 fields below */ u32 dt_strings_size; /* size of the DT strings block */ + /* version 17 fields below */ + u32 dt_struct_size; /* size of the DT structure block */ }; @@ -68,7 +72,7 @@ typedef u32 ihandle; struct property { char *name; int length; - unsigned char *value; + void *value; struct property *next; }; @@ -108,14 +112,6 @@ static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_e } -/* OBSOLETE: Old style node lookup */ -extern struct device_node *find_devices(const char *name); -extern struct device_node *find_type_devices(const char *type); -extern struct device_node *find_path_device(const char *path); -extern struct device_node *find_compatible_devices(const char *type, - const char *compat); -extern struct device_node *find_all_nodes(void); - /* New style node lookup */ extern struct device_node *of_find_node_by_name(struct device_node *from, const char *name); @@ -159,15 +155,17 @@ extern void of_detach_node(const struct device_node *); extern void finish_device_tree(void); extern void unflatten_device_tree(void); extern void early_init_devtree(void *); -extern int device_is_compatible(const struct device_node *device, +extern int of_device_is_compatible(const struct device_node *device, const char *); +#define device_is_compatible(d, c) of_device_is_compatible((d), (c)) extern int machine_is_compatible(const char *compat); -extern const void *get_property(const struct device_node *node, +extern const void *of_get_property(const struct device_node *node, const char *name, int *lenp); +#define get_property(a, b, c) of_get_property((a), (b), (c)) extern void print_properties(struct device_node *node); -extern int prom_n_addr_cells(struct device_node* np); -extern int prom_n_size_cells(struct device_node* np); +extern int of_n_addr_cells(struct device_node* np); +extern int of_n_size_cells(struct device_node* np); extern int prom_n_intr_cells(struct device_node* np); extern void prom_get_irq_senses(unsigned char *senses, int off, int max); extern int prom_add_property(struct device_node* np, struct property* prop); @@ -350,6 +348,16 @@ static inline int of_irq_to_resource(struct device_node *dev, int index, struct return irq; } +static inline void __iomem *of_iomap(struct device_node *np, int index) +{ + struct resource res; + + if (of_address_to_resource(np, index, &res)) + return NULL; + + return ioremap(res.start, 1 + res.end - res.start); +} + #endif /* __KERNEL__ */ #endif /* _POWERPC_PROM_H */ diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h index 0d7f016..749c7f9 100644 --- a/include/asm-powerpc/reg.h +++ b/include/asm-powerpc/reg.h @@ -469,12 +469,68 @@ #define SPRN_SIAR 780 #define SPRN_SDAR 781 -#define PA6T_SPRN_PMC0 787 -#define PA6T_SPRN_PMC1 788 -#define PA6T_SPRN_PMC2 789 -#define PA6T_SPRN_PMC3 790 -#define PA6T_SPRN_PMC4 791 -#define PA6T_SPRN_PMC5 792 +#define SPRN_PA6T_MMCR0 795 +#define PA6T_MMCR0_EN0 0x0000000000000001UL +#define PA6T_MMCR0_EN1 0x0000000000000002UL +#define PA6T_MMCR0_EN2 0x0000000000000004UL +#define PA6T_MMCR0_EN3 0x0000000000000008UL +#define PA6T_MMCR0_EN4 0x0000000000000010UL +#define PA6T_MMCR0_EN5 0x0000000000000020UL +#define PA6T_MMCR0_SUPEN 0x0000000000000040UL +#define PA6T_MMCR0_PREN 0x0000000000000080UL +#define PA6T_MMCR0_HYPEN 0x0000000000000100UL +#define PA6T_MMCR0_FCM0 0x0000000000000200UL +#define PA6T_MMCR0_FCM1 0x0000000000000400UL +#define PA6T_MMCR0_INTGEN 0x0000000000000800UL +#define PA6T_MMCR0_INTEN0 0x0000000000001000UL +#define PA6T_MMCR0_INTEN1 0x0000000000002000UL +#define PA6T_MMCR0_INTEN2 0x0000000000004000UL +#define PA6T_MMCR0_INTEN3 0x0000000000008000UL +#define PA6T_MMCR0_INTEN4 0x0000000000010000UL +#define PA6T_MMCR0_INTEN5 0x0000000000020000UL +#define PA6T_MMCR0_DISCNT 0x0000000000040000UL +#define PA6T_MMCR0_UOP 0x0000000000080000UL +#define PA6T_MMCR0_TRG 0x0000000000100000UL +#define PA6T_MMCR0_TRGEN 0x0000000000200000UL +#define PA6T_MMCR0_TRGREG 0x0000000001600000UL +#define PA6T_MMCR0_SIARLOG 0x0000000002000000UL +#define PA6T_MMCR0_SDARLOG 0x0000000004000000UL +#define PA6T_MMCR0_PROEN 0x0000000008000000UL +#define PA6T_MMCR0_PROLOG 0x0000000010000000UL +#define PA6T_MMCR0_DAMEN2 0x0000000020000000UL +#define PA6T_MMCR0_DAMEN3 0x0000000040000000UL +#define PA6T_MMCR0_DAMEN4 0x0000000080000000UL +#define PA6T_MMCR0_DAMEN5 0x0000000100000000UL +#define PA6T_MMCR0_DAMSEL2 0x0000000200000000UL +#define PA6T_MMCR0_DAMSEL3 0x0000000400000000UL +#define PA6T_MMCR0_DAMSEL4 0x0000000800000000UL +#define PA6T_MMCR0_DAMSEL5 0x0000001000000000UL +#define PA6T_MMCR0_HANDDIS 0x0000002000000000UL +#define PA6T_MMCR0_PCTEN 0x0000004000000000UL +#define PA6T_MMCR0_SOCEN 0x0000008000000000UL +#define PA6T_MMCR0_SOCMOD 0x0000010000000000UL + +#define SPRN_PA6T_MMCR1 798 +#define PA6T_MMCR1_ES2 0x00000000000000ffUL +#define PA6T_MMCR1_ES3 0x000000000000ff00UL +#define PA6T_MMCR1_ES4 0x0000000000ff0000UL +#define PA6T_MMCR1_ES5 0x00000000ff000000UL + +#define SPRN_PA6T_SIAR 780 +#define SPRN_PA6T_UPMC0 771 +#define SPRN_PA6T_UPMC1 772 +#define SPRN_PA6T_UPMC2 773 +#define SPRN_PA6T_UPMC3 774 +#define SPRN_PA6T_UPMC4 775 +#define SPRN_PA6T_UPMC5 776 +#define SPRN_PA6T_UMMCR0 779 +#define SPRN_PA6T_UMMCR1 782 +#define SPRN_PA6T_PMC0 787 +#define SPRN_PA6T_PMC1 788 +#define SPRN_PA6T_PMC2 789 +#define SPRN_PA6T_PMC3 790 +#define SPRN_PA6T_PMC4 791 +#define SPRN_PA6T_PMC5 792 #else /* 32-bit */ #define SPRN_MMCR0 952 /* Monitor Mode Control Register 0 */ diff --git a/include/asm-powerpc/spu_csa.h b/include/asm-powerpc/spu_csa.h index 8aad061..02e56a6 100644 --- a/include/asm-powerpc/spu_csa.h +++ b/include/asm-powerpc/spu_csa.h @@ -242,6 +242,7 @@ struct spu_state { u64 spu_chnldata_RW[32]; u32 spu_mailbox_data[4]; u32 pu_mailbox_data[1]; + u64 dar, dsisr; unsigned long suspend_time; spinlock_t register_lock; }; diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h index f7b1227..d3e0906 100644 --- a/include/asm-powerpc/system.h +++ b/include/asm-powerpc/system.h @@ -131,6 +131,7 @@ extern void enable_kernel_altivec(void); extern void giveup_altivec(struct task_struct *); extern void load_up_altivec(struct task_struct *); extern int emulate_altivec(struct pt_regs *); +extern void enable_kernel_spe(void); extern void giveup_spe(struct task_struct *); extern void load_up_spe(struct task_struct *); extern int fix_alignment(struct pt_regs *); diff --git a/include/asm-powerpc/tlb.h b/include/asm-powerpc/tlb.h index 4e2a834..0a17682 100644 --- a/include/asm-powerpc/tlb.h +++ b/include/asm-powerpc/tlb.h @@ -38,7 +38,6 @@ extern void pte_free_finish(void); static inline void tlb_flush(struct mmu_gather *tlb) { - flush_tlb_pending(); pte_free_finish(); } diff --git a/include/asm-powerpc/tlbflush.h b/include/asm-powerpc/tlbflush.h index 93c7d0c..86e6266 100644 --- a/include/asm-powerpc/tlbflush.h +++ b/include/asm-powerpc/tlbflush.h @@ -17,10 +17,73 @@ */ #ifdef __KERNEL__ - struct mm_struct; +struct vm_area_struct; + +#if defined(CONFIG_4xx) || defined(CONFIG_8xx) || defined(CONFIG_FSL_BOOKE) +/* + * TLB flushing for software loaded TLB chips + * + * TODO: (CONFIG_FSL_BOOKE) determine if flush_tlb_range & + * flush_tlb_kernel_range are best implemented as tlbia vs + * specific tlbie's + */ + +extern void _tlbie(unsigned long address); + +#if defined(CONFIG_40x) || defined(CONFIG_8xx) +#define _tlbia() asm volatile ("tlbia; sync" : : : "memory") +#else /* CONFIG_44x || CONFIG_FSL_BOOKE */ +extern void _tlbia(void); +#endif + +static inline void flush_tlb_mm(struct mm_struct *mm) +{ + _tlbia(); +} + +static inline void flush_tlb_page(struct vm_area_struct *vma, + unsigned long vmaddr) +{ + _tlbie(vmaddr); +} + +static inline void flush_tlb_page_nohash(struct vm_area_struct *vma, + unsigned long vmaddr) +{ + _tlbie(vmaddr); +} + +static inline void flush_tlb_range(struct vm_area_struct *vma, + unsigned long start, unsigned long end) +{ + _tlbia(); +} + +static inline void flush_tlb_kernel_range(unsigned long start, + unsigned long end) +{ + _tlbia(); +} -#ifdef CONFIG_PPC64 +#elif defined(CONFIG_PPC32) +/* + * TLB flushing for "classic" hash-MMMU 32-bit CPUs, 6xx, 7xx, 7xxx + */ +extern void _tlbie(unsigned long address); +extern void _tlbia(void); + +extern void flush_tlb_mm(struct mm_struct *mm); +extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); +extern void flush_tlb_page_nohash(struct vm_area_struct *vma, unsigned long addr); +extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, + unsigned long end); +extern void flush_tlb_kernel_range(unsigned long start, unsigned long end); + +#else +/* + * TLB flushing for 64-bit has-MMU CPUs + */ #include <linux/percpu.h> #include <asm/page.h> @@ -28,117 +91,90 @@ struct mm_struct; #define PPC64_TLB_BATCH_NR 192 struct ppc64_tlb_batch { - unsigned long index; - struct mm_struct *mm; - real_pte_t pte[PPC64_TLB_BATCH_NR]; - unsigned long vaddr[PPC64_TLB_BATCH_NR]; - unsigned int psize; + int active; + unsigned long index; + struct mm_struct *mm; + real_pte_t pte[PPC64_TLB_BATCH_NR]; + unsigned long vaddr[PPC64_TLB_BATCH_NR]; + unsigned int psize; }; DECLARE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch); extern void __flush_tlb_pending(struct ppc64_tlb_batch *batch); -static inline void flush_tlb_pending(void) +extern void hpte_need_flush(struct mm_struct *mm, unsigned long addr, + pte_t *ptep, unsigned long pte, int huge); + +#define __HAVE_ARCH_ENTER_LAZY_MMU_MODE + +static inline void arch_enter_lazy_mmu_mode(void) +{ + struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); + + batch->active = 1; +} + +static inline void arch_leave_lazy_mmu_mode(void) { - struct ppc64_tlb_batch *batch = &get_cpu_var(ppc64_tlb_batch); + struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); if (batch->index) __flush_tlb_pending(batch); - put_cpu_var(ppc64_tlb_batch); + batch->active = 0; } +#define arch_flush_lazy_mmu_mode() do {} while (0) + + extern void flush_hash_page(unsigned long va, real_pte_t pte, int psize, int local); extern void flush_hash_range(unsigned long number, int local); -#else /* CONFIG_PPC64 */ - -#include <linux/mm.h> - -extern void _tlbie(unsigned long address); -extern void _tlbia(void); - -/* - * TODO: (CONFIG_FSL_BOOKE) determine if flush_tlb_range & - * flush_tlb_kernel_range are best implemented as tlbia vs - * specific tlbie's - */ - -#if (defined(CONFIG_4xx) && !defined(CONFIG_44x)) || defined(CONFIG_8xx) -#define flush_tlb_pending() asm volatile ("tlbia; sync" : : : "memory") -#elif defined(CONFIG_4xx) || defined(CONFIG_FSL_BOOKE) -#define flush_tlb_pending() _tlbia() -#endif - -/* - * This gets called at the end of handling a page fault, when - * the kernel has put a new PTE into the page table for the process. - * We use it to ensure coherency between the i-cache and d-cache - * for the page which has just been mapped in. - * On machines which use an MMU hash table, we use this to put a - * corresponding HPTE into the hash table ahead of time, instead of - * waiting for the inevitable extra hash-table miss exception. - */ -extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); - -#endif /* CONFIG_PPC64 */ - -#if defined(CONFIG_PPC64) || defined(CONFIG_4xx) || \ - defined(CONFIG_FSL_BOOKE) || defined(CONFIG_8xx) static inline void flush_tlb_mm(struct mm_struct *mm) { - flush_tlb_pending(); } static inline void flush_tlb_page(struct vm_area_struct *vma, - unsigned long vmaddr) + unsigned long vmaddr) { -#ifdef CONFIG_PPC64 - flush_tlb_pending(); -#else - _tlbie(vmaddr); -#endif } static inline void flush_tlb_page_nohash(struct vm_area_struct *vma, unsigned long vmaddr) { -#ifndef CONFIG_PPC64 - _tlbie(vmaddr); -#endif } static inline void flush_tlb_range(struct vm_area_struct *vma, - unsigned long start, unsigned long end) + unsigned long start, unsigned long end) { - flush_tlb_pending(); } static inline void flush_tlb_kernel_range(unsigned long start, - unsigned long end) + unsigned long end) { - flush_tlb_pending(); } -#else /* 6xx, 7xx, 7xxx cpus */ - -extern void flush_tlb_mm(struct mm_struct *mm); -extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); -extern void flush_tlb_page_nohash(struct vm_area_struct *vma, unsigned long addr); -extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, - unsigned long end); -extern void flush_tlb_kernel_range(unsigned long start, unsigned long end); - #endif /* + * This gets called at the end of handling a page fault, when + * the kernel has put a new PTE into the page table for the process. + * We use it to ensure coherency between the i-cache and d-cache + * for the page which has just been mapped in. + * On machines which use an MMU hash table, we use this to put a + * corresponding HPTE into the hash table ahead of time, instead of + * waiting for the inevitable extra hash-table miss exception. + */ +extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); + +/* * This is called in munmap when we have freed up some page-table * pages. We don't need to do anything here, there's nothing special * about our page-table pages. -- paulus */ static inline void flush_tlb_pgtables(struct mm_struct *mm, - unsigned long start, unsigned long end) + unsigned long start, unsigned long end) { } diff --git a/include/asm-powerpc/uaccess.h b/include/asm-powerpc/uaccess.h index adbf16b..8e798e3 100644 --- a/include/asm-powerpc/uaccess.h +++ b/include/asm-powerpc/uaccess.h @@ -110,12 +110,18 @@ struct exception_table_entry { __get_user_nocheck((x), (ptr), sizeof(*(ptr))) #define __put_user(x, ptr) \ __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) + #ifndef __powerpc64__ #define __get_user64(x, ptr) \ __get_user64_nocheck((x), (ptr), sizeof(*(ptr))) #define __put_user64(x, ptr) __put_user(x, ptr) #endif +#define __get_user_inatomic(x, ptr) \ + __get_user_nosleep((x), (ptr), sizeof(*(ptr))) +#define __put_user_inatomic(x, ptr) \ + __put_user_nosleep((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) + #define __get_user_unaligned __get_user #define __put_user_unaligned __put_user @@ -198,6 +204,16 @@ do { \ __pu_err; \ }) +#define __put_user_nosleep(x, ptr, size) \ +({ \ + long __pu_err; \ + __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ + __chk_user_ptr(ptr); \ + __put_user_size((x), __pu_addr, (size), __pu_err); \ + __pu_err; \ +}) + + extern long __get_user_bad(void); #define __get_user_asm(x, addr, err, op) \ @@ -297,6 +313,18 @@ do { \ __gu_err; \ }) +#define __get_user_nosleep(x, ptr, size) \ +({ \ + long __gu_err; \ + unsigned long __gu_val; \ + const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ + __chk_user_ptr(ptr); \ + __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ + (x) = (__typeof__(*(ptr)))__gu_val; \ + __gu_err; \ +}) + + /* more complex routines */ extern unsigned long __copy_tofrom_user(void __user *to, diff --git a/include/asm-powerpc/uic.h b/include/asm-powerpc/uic.h new file mode 100644 index 0000000..970eb7e --- /dev/null +++ b/include/asm-powerpc/uic.h @@ -0,0 +1,23 @@ +/* + * include/asm-powerpc/uic.h + * + * IBM PPC4xx UIC external definitions and structure. + * + * Maintainer: David Gibson <dwg@au1.ibm.com> + * Copyright 2007 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. + */ +#ifndef _ASM_POWERPC_UIC_H +#define _ASM_POWERPC_UIC_H + +#ifdef __KERNEL__ + +extern void __init uic_init_tree(void); +extern unsigned int uic_get_irq(void); + +#endif /* __KERNEL__ */ +#endif /* _ASM_POWERPC_UIC_H */ diff --git a/include/asm-ppc/ibm4xx.h b/include/asm-ppc/ibm4xx.h index 92fd02d..ed6891a 100644 --- a/include/asm-ppc/ibm4xx.h +++ b/include/asm-ppc/ibm4xx.h @@ -47,12 +47,8 @@ #include <platforms/4xx/walnut.h> #endif -#if defined(CONFIG_XILINX_ML300) -#include <platforms/4xx/xilinx_ml300.h> -#endif - -#if defined(CONFIG_XILINX_ML403) -#include <platforms/4xx/xilinx_ml403.h> +#if defined(CONFIG_XILINX_VIRTEX) +#include <platforms/4xx/virtex.h> #endif #ifndef __ASSEMBLY__ diff --git a/include/asm-ppc/ppc_sys.h b/include/asm-ppc/ppc_sys.h index 40f197a..de99e92 100644 --- a/include/asm-ppc/ppc_sys.h +++ b/include/asm-ppc/ppc_sys.h @@ -33,8 +33,6 @@ #include <asm/mpc52xx.h> #elif defined(CONFIG_MPC10X_BRIDGE) #include <asm/mpc10x.h> -#elif defined(CONFIG_XILINX_VIRTEX) -#include <platforms/4xx/virtex.h> #else #error "need definition of ppc_sys_devices" #endif diff --git a/include/asm-ppc/prom.h b/include/asm-ppc/prom.h index adc5ae7..901f7fa 100644 --- a/include/asm-ppc/prom.h +++ b/include/asm-ppc/prom.h @@ -34,7 +34,8 @@ extern unsigned long sub_reloc_offset(unsigned long); */ #define machine_is_compatible(x) 0 #define of_find_compatible_node(f, t, c) NULL -#define get_property(p, n, l) NULL +#define of_get_property(p, n, l) NULL +#define get_property(a, b, c) of_get_property((a), (b), (c)) #endif /* _PPC_PROM_H */ #endif /* __KERNEL__ */ diff --git a/include/linux/pmu.h b/include/linux/pmu.h index 7831773..b0952e5 100644 --- a/include/linux/pmu.h +++ b/include/linux/pmu.h @@ -168,24 +168,16 @@ extern int pmu_get_model(void); struct pmu_sleep_notifier { - int (*notifier_call)(struct pmu_sleep_notifier *self, int when); + void (*notifier_call)(struct pmu_sleep_notifier *self, int when); int priority; struct list_head list; }; /* Code values for calling sleep/wakeup handlers - * - * Note: If a sleep request got cancelled, all drivers will get - * the PBOOK_SLEEP_REJECT, even those who didn't get the PBOOK_SLEEP_REQUEST. */ #define PBOOK_SLEEP_REQUEST 1 #define PBOOK_SLEEP_NOW 2 -#define PBOOK_SLEEP_REJECT 3 -#define PBOOK_WAKE 4 - -/* Result codes returned by the notifiers */ -#define PBOOK_SLEEP_OK 0 -#define PBOOK_SLEEP_REFUSE -1 +#define PBOOK_WAKE 3 /* priority levels in notifiers */ #define SLEEP_LEVEL_VIDEO 100 /* Video driver (first wake) */ diff --git a/sound/aoa/codecs/snd-aoa-codec-onyx.c b/sound/aoa/codecs/snd-aoa-codec-onyx.c index b00fc48..7f980be 100644 --- a/sound/aoa/codecs/snd-aoa-codec-onyx.c +++ b/sound/aoa/codecs/snd-aoa-codec-onyx.c @@ -1062,9 +1062,9 @@ static int onyx_i2c_attach(struct i2c_adapter *adapter) while ((dev = of_get_next_child(busnode, dev)) != NULL) { if (device_is_compatible(dev, "pcm3052")) { - u32 *addr; + const u32 *addr; printk(KERN_DEBUG PFX "found pcm3052\n"); - addr = (u32 *) get_property(dev, "reg", NULL); + addr = of_get_property(dev, "reg", NULL); if (!addr) return -ENODEV; return onyx_create(adapter, dev, (*addr)>>1); diff --git a/sound/aoa/codecs/snd-aoa-codec-tas.c b/sound/aoa/codecs/snd-aoa-codec-tas.c index 2cd81fa..ceca384 100644 --- a/sound/aoa/codecs/snd-aoa-codec-tas.c +++ b/sound/aoa/codecs/snd-aoa-codec-tas.c @@ -939,9 +939,9 @@ static int tas_i2c_attach(struct i2c_adapter *adapter) while ((dev = of_get_next_child(busnode, dev)) != NULL) { if (device_is_compatible(dev, "tas3004")) { - u32 *addr; + const u32 *addr; printk(KERN_DEBUG PFX "found tas3004\n"); - addr = (u32 *) get_property(dev, "reg", NULL); + addr = of_get_property(dev, "reg", NULL); if (!addr) continue; return tas_create(adapter, dev, ((*addr) >> 1) & 0x7f); @@ -950,9 +950,10 @@ static int tas_i2c_attach(struct i2c_adapter *adapter) * property that says 'tas3004', they just have a 'deq' * node without any such property... */ if (strcmp(dev->name, "deq") == 0) { - u32 *_addr, addr; + const u32 *_addr; + u32 addr; printk(KERN_DEBUG PFX "found 'deq' node\n"); - _addr = (u32 *) get_property(dev, "i2c-address", NULL); + _addr = of_get_property(dev, "i2c-address", NULL); if (!_addr) continue; addr = ((*_addr) >> 1) & 0x7f; diff --git a/sound/aoa/core/snd-aoa-gpio-feature.c b/sound/aoa/core/snd-aoa-gpio-feature.c index 2b03bc7..805dcbf 100644 --- a/sound/aoa/core/snd-aoa-gpio-feature.c +++ b/sound/aoa/core/snd-aoa-gpio-feature.c @@ -55,7 +55,7 @@ static struct device_node *get_gpio(char *name, int *gpioactiveptr) { struct device_node *np, *gpio; - u32 *reg; + const u32 *reg; const char *audio_gpio; *gpioptr = -1; @@ -71,7 +71,7 @@ static struct device_node *get_gpio(char *name, if (!gpio) return NULL; while ((np = of_get_next_child(gpio, np))) { - audio_gpio = get_property(np, "audio-gpio", NULL); + audio_gpio = of_get_property(np, "audio-gpio", NULL); if (!audio_gpio) continue; if (strcmp(audio_gpio, name) == 0) @@ -84,7 +84,7 @@ static struct device_node *get_gpio(char *name, return NULL; } - reg = (u32 *)get_property(np, "reg", NULL); + reg = of_get_property(np, "reg", NULL); if (!reg) return NULL; @@ -96,7 +96,7 @@ static struct device_node *get_gpio(char *name, if (*gpioptr < 0x50) *gpioptr += 0x50; - reg = (u32 *)get_property(np, "audio-gpio-active-state", NULL); + reg = of_get_property(np, "audio-gpio-active-state", NULL); if (!reg) /* Apple seems to default to 1, but * that doesn't seem right at least on most diff --git a/sound/aoa/fabrics/snd-aoa-fabric-layout.c b/sound/aoa/fabrics/snd-aoa-fabric-layout.c index 1b94ba6..9880628 100644 --- a/sound/aoa/fabrics/snd-aoa-fabric-layout.c +++ b/sound/aoa/fabrics/snd-aoa-fabric-layout.c @@ -724,7 +724,7 @@ static int check_codec(struct aoa_codec *codec, struct layout_dev *ldev, struct codec_connect_info *cci) { - u32 *ref; + const u32 *ref; char propname[32]; struct codec_connection *cc; @@ -732,7 +732,7 @@ static int check_codec(struct aoa_codec *codec, if (codec->node && (strcmp(codec->node->name, "codec") == 0)) { snprintf(propname, sizeof(propname), "platform-%s-codec-ref", codec->name); - ref = (u32*)get_property(ldev->sound, propname, NULL); + ref = of_get_property(ldev->sound, propname, NULL); if (!ref) { printk(KERN_INFO "snd-aoa-fabric-layout: " "required property %s not present\n", propname); @@ -946,7 +946,7 @@ static struct aoa_fabric layout_fabric = { static int aoa_fabric_layout_probe(struct soundbus_dev *sdev) { struct device_node *sound = NULL; - unsigned int *layout_id; + const unsigned int *layout_id; struct layout *layout; struct layout_dev *ldev = NULL; int err; @@ -962,7 +962,7 @@ static int aoa_fabric_layout_probe(struct soundbus_dev *sdev) } if (!sound) return -ENODEV; - layout_id = (unsigned int *) get_property(sound, "layout-id", NULL); + layout_id = of_get_property(sound, "layout-id", NULL); if (!layout_id) goto outnodev; printk(KERN_INFO "snd-aoa-fabric-layout: found bus with layout %d\n", diff --git a/sound/aoa/soundbus/core.c b/sound/aoa/soundbus/core.c index 418a98a..8b2e9b9 100644 --- a/sound/aoa/soundbus/core.c +++ b/sound/aoa/soundbus/core.c @@ -61,7 +61,7 @@ static int soundbus_uevent(struct device *dev, char **envp, int num_envp, { struct soundbus_dev * soundbus_dev; struct of_device * of; - char *compat; + const char *compat; int retval = 0, i = 0, length = 0; int cplen, seen = 0; @@ -91,7 +91,7 @@ static int soundbus_uevent(struct device *dev, char **envp, int num_envp, * it's not really legal to split it out with commas. We split it * up using a number of environment variables instead. */ - compat = (char *) get_property(of->node, "compatible", &cplen); + compat = of_get_property(of->node, "compatible", &cplen); while (compat && cplen > 0) { int tmp = length; retval = add_uevent_var(envp, num_envp, &i, diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-core.c b/sound/aoa/soundbus/i2sbus/i2sbus-core.c index e36f6aa..79fc4bc 100644 --- a/sound/aoa/soundbus/i2sbus/i2sbus-core.c +++ b/sound/aoa/soundbus/i2sbus/i2sbus-core.c @@ -122,7 +122,7 @@ static int i2sbus_get_and_fixup_rsrc(struct device_node *np, int index, { struct device_node *parent; int pindex, rc = -ENXIO; - u32 *reg; + const u32 *reg; /* Machines with layout 76 and 36 (K2 based) have a weird device * tree what we need to special case. @@ -141,7 +141,7 @@ static int i2sbus_get_and_fixup_rsrc(struct device_node *np, int index, rc = of_address_to_resource(parent, pindex, res); if (rc) goto bail; - reg = (u32 *)get_property(np, "reg", NULL); + reg = of_get_property(np, "reg", NULL); if (reg == NULL) { rc = -ENXIO; goto bail; @@ -188,8 +188,8 @@ static int i2sbus_add_dev(struct macio_dev *macio, } } if (i == 1) { - u32 *layout_id; - layout_id = (u32*) get_property(sound, "layout-id", NULL); + const u32 *layout_id = + of_get_property(sound, "layout-id", NULL); if (layout_id) { layout = *layout_id; snprintf(dev->sound.modalias, 32, diff --git a/sound/oss/dmasound/dmasound_awacs.c b/sound/oss/dmasound/dmasound_awacs.c index 37773b1..730fa1d 100644 --- a/sound/oss/dmasound/dmasound_awacs.c +++ b/sound/oss/dmasound/dmasound_awacs.c @@ -257,7 +257,7 @@ static volatile struct dbdma_cmd *emergency_dbdma_cmd; /* * Stuff for restoring after a sleep. */ -static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when); +static void awacs_sleep_notify(struct pmu_sleep_notifier *self, int when); struct pmu_sleep_notifier awacs_sleep_notifier = { awacs_sleep_notify, SLEEP_LEVEL_SOUND, }; @@ -346,36 +346,42 @@ int gpio_headphone_irq; int setup_audio_gpio(const char *name, const char* compatible, int *gpio_addr, int* gpio_pol) { + struct device_node *gpiop; struct device_node *np; const u32* pp; + int ret = -ENODEV; - np = find_devices("gpio"); - if (!np) - return -ENODEV; + gpiop = of_find_node_by_name(NULL, "gpio"); + if (!gpiop) + goto done; - np = np->child; + np = of_get_next_child(gpiop, NULL); while(np != 0) { if (name) { const char *property = - get_property(np,"audio-gpio",NULL); + of_get_property(np,"audio-gpio",NULL); if (property != 0 && strcmp(property,name) == 0) break; } else if (compatible && device_is_compatible(np, compatible)) break; - np = np->sibling; + np = of_get_next_child(gpiop, np); } if (!np) - return -ENODEV; - pp = get_property(np, "AAPL,address", NULL); + goto done; + pp = of_get_property(np, "AAPL,address", NULL); if (!pp) - return -ENODEV; + goto done; *gpio_addr = (*pp) & 0x0000ffff; - pp = get_property(np, "audio-gpio-active-state", NULL); + pp = of_get_property(np, "audio-gpio-active-state", NULL); if (pp) *gpio_pol = *pp; else *gpio_pol = 1; - return irq_of_parse_and_map(np, 0); + ret = irq_of_parse_and_map(np, 0); +done: + of_node_put(np); + of_node_put(gpiop); + return ret; } static inline void @@ -578,7 +584,7 @@ tas_mixer_ioctl(u_int cmd, u_long arg) } static void __init -tas_init_frame_rates(unsigned int *prop, unsigned int l) +tas_init_frame_rates(const unsigned int *prop, unsigned int l) { int i ; if (prop) { @@ -1419,7 +1425,7 @@ load_awacs(void) * Save state when going to sleep, restore it afterwards. */ /* FIXME: sort out disabling/re-enabling of read stuff as well */ -static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when) +static void awacs_sleep_notify(struct pmu_sleep_notifier *self, int when) { unsigned long flags; @@ -1548,7 +1554,6 @@ static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when) spin_unlock_irqrestore(&dmasound.lock, flags); UNLOCK(); } - return PBOOK_SLEEP_OK; } #endif /* CONFIG_PM */ @@ -2553,32 +2558,33 @@ set_model(void) static struct device_node* __init get_snd_io_node(void) { - struct device_node *np = NULL; + struct device_node *np; /* set up awacs_node for early OF which doesn't have a full set of * properties on davbus - */ - - awacs_node = find_devices("awacs"); + */ + awacs_node = of_find_node_by_name(NULL, "awacs"); if (awacs_node) awacs_revision = AWACS_AWACS; /* powermac models after 9500 (other than those which use DACA or * Tumbler) have a node called "davbus". */ - np = find_devices("davbus"); + np = of_find_node_by_name(NULL, "davbus"); /* * if we didn't find a davbus device, try 'i2s-a' since * this seems to be what iBooks (& Tumbler) have. */ - if (np == NULL) - np = i2s_node = find_devices("i2s-a"); + if (np == NULL) { + i2s_node = of_find_node_by_name(NULL, "i2s-a"); + np = of_node_get(i2s_node); + } /* if we didn't find this - perhaps we are on an early model * which _only_ has an 'awacs' node */ if (np == NULL && awacs_node) - np = awacs_node ; + np = of_node_get(awacs_node); /* if we failed all these return null - this will cause the * driver to give up... @@ -2597,9 +2603,9 @@ get_snd_info_node(struct device_node *io) { struct device_node *info; - info = find_devices("sound"); - while (info && info->parent != io) - info = info->next; + for_each_node_by_name(info, "sound") + if (info->parent == io) + break; return info; } @@ -2635,11 +2641,17 @@ get_codec_type(struct device_node *info) static void __init get_expansion_type(void) { - if (find_devices("perch") != NULL) + struct device_node *dn; + + dn = of_find_node_by_name(NULL, "perch"); + if (dn != NULL) has_perch = 1; + of_node_put(dn); - if (find_devices("pb-ziva-pc") != NULL) + dn = of_find_node_by_name(NULL, "pb-ziva-pc"); + if (dn != NULL) has_ziva = 1; + of_node_put(dn); /* need to work out how we deal with iMac SRS module */ } @@ -2652,7 +2664,7 @@ get_expansion_type(void) */ static void __init -awacs_init_frame_rates(unsigned int *prop, unsigned int l) +awacs_init_frame_rates(const unsigned int *prop, unsigned int l) { int i ; if (prop) { @@ -2675,7 +2687,7 @@ awacs_init_frame_rates(unsigned int *prop, unsigned int l) } static void __init -burgundy_init_frame_rates(unsigned int *prop, unsigned int l) +burgundy_init_frame_rates(const unsigned int *prop, unsigned int l) { int temp[9] ; int i = 0 ; @@ -2701,7 +2713,7 @@ if (i > 1){ } static void __init -daca_init_frame_rates(unsigned int *prop, unsigned int l) +daca_init_frame_rates(const unsigned int *prop, unsigned int l) { int temp[9] ; int i = 0 ; @@ -2728,7 +2740,7 @@ if (i > 1){ } static void __init -init_frame_rates(unsigned int *prop, unsigned int l) +init_frame_rates(const unsigned int *prop, unsigned int l) { switch (awacs_revision) { case AWACS_TUMBLER: @@ -2828,7 +2840,7 @@ int __init dmasound_awacs_init(void) #ifdef DEBUG_DMASOUND printk("dmasound_pmac: couldn't find sound io OF node\n"); #endif - return -ENODEV ; + goto no_device; } /* find the OF node that tells us about the sound sub-system @@ -2840,7 +2852,7 @@ printk("dmasound_pmac: couldn't find sound io OF node\n"); #ifdef DEBUG_DMASOUND printk("dmasound_pmac: couldn't find 'sound' OF node\n"); #endif - return -ENODEV ; + goto no_device; } } @@ -2849,7 +2861,7 @@ printk("dmasound_pmac: couldn't find 'sound' OF node\n"); #ifdef DEBUG_DMASOUND printk("dmasound_pmac: couldn't find a Codec we can handle\n"); #endif - return -ENODEV ; /* we don't know this type of h/w */ + goto no_device; /* we don't know this type of h/w */ } /* set up perch, ziva, SRS or whatever else we have as sound @@ -2867,11 +2879,12 @@ printk("dmasound_pmac: couldn't find a Codec we can handle\n"); * machines). */ if (awacs_node) { - io = awacs_node ; + of_node_put(io); + io = of_node_get(awacs_node); if (of_get_address(io, 2, NULL, NULL) == NULL) { printk("dmasound_pmac: can't use %s\n", io->full_name); - return -ENODEV; + goto no_device; } } else printk("dmasound_pmac: can't use %s\n", io->full_name); @@ -2882,7 +2895,7 @@ printk("dmasound_pmac: couldn't find a Codec we can handle\n"); awacs_rsrc[0].end - awacs_rsrc[0].start + 1, " (IO)") == NULL) { printk(KERN_ERR "dmasound: can't request IO resource !\n"); - return -ENODEV; + goto no_device; } if (of_address_to_resource(io, 1, &awacs_rsrc[1]) || request_mem_region(awacs_rsrc[1].start, @@ -2891,7 +2904,7 @@ printk("dmasound_pmac: couldn't find a Codec we can handle\n"); release_mem_region(awacs_rsrc[0].start, awacs_rsrc[0].end - awacs_rsrc[0].start + 1); printk(KERN_ERR "dmasound: can't request Tx DMA resource !\n"); - return -ENODEV; + goto no_device; } if (of_address_to_resource(io, 2, &awacs_rsrc[2]) || request_mem_region(awacs_rsrc[2].start, @@ -2902,7 +2915,7 @@ printk("dmasound_pmac: couldn't find a Codec we can handle\n"); release_mem_region(awacs_rsrc[1].start, awacs_rsrc[1].end - awacs_rsrc[1].start + 1); printk(KERN_ERR "dmasound: can't request Rx DMA resource !\n"); - return -ENODEV; + goto no_device; } awacs_beep_dev = input_allocate_device(); @@ -2914,7 +2927,7 @@ printk("dmasound_pmac: couldn't find a Codec we can handle\n"); release_mem_region(awacs_rsrc[2].start, awacs_rsrc[2].end - awacs_rsrc[2].start + 1); printk(KERN_ERR "dmasound: can't allocate input device !\n"); - return -ENOMEM; + goto no_device; } awacs_beep_dev->name = "dmasound beeper"; @@ -2942,7 +2955,8 @@ printk("dmasound_pmac: couldn't find a Codec we can handle\n"); awacs_rx_irq = irq_of_parse_and_map(io, 2); /* Hack for legacy crap that will be killed someday */ - awacs_node = io; + of_node_put(awacs_node); + awacs_node = of_node_get(io); /* if we have an awacs or screamer - probe the chip to make * sure we have the right revision. @@ -2973,24 +2987,26 @@ printk("dmasound_pmac: Awacs/Screamer Codec Mfct: %d Rev %d\n", mfg, rev); */ if (info) { - unsigned int *prop, l; + const unsigned int *prop; + unsigned int l; sound_device_id = 0; /* device ID appears post g3 b&w */ - prop = (unsigned int *)get_property(info, "device-id", NULL); + prop = of_get_property(info, "device-id", NULL); if (prop != 0) sound_device_id = *prop; /* look for a property saying what sample rates are available */ - prop = (unsigned int *)get_property(info, "sample-rates", &l); + prop = of_get_property(info, "sample-rates", &l); if (prop == 0) - prop = (unsigned int *) get_property - (info, "output-frame-rates", &l); + prop = of_get_property(info, "output-frame-rates", &l); /* if it's there use it to set up frame rates */ init_frame_rates(prop, l) ; + of_node_put(info); + info = NULL; } if (awacs) @@ -3160,7 +3176,16 @@ printk("dmasound_pmac: Awacs/Screamer Codec Mfct: %d Rev %d\n", mfg, rev); */ input_register_device(awacs_beep_dev); + of_node_put(io); + return dmasound_init(); + +no_device: + of_node_put(info); + of_node_put(awacs_node); + of_node_put(i2s_node); + of_node_put(io); + return -ENODEV ; } static void __exit dmasound_awacs_cleanup(void) @@ -3179,6 +3204,8 @@ static void __exit dmasound_awacs_cleanup(void) } dmasound_deinit(); + of_node_put(awacs_node); + of_node_put(i2s_node); } MODULE_DESCRIPTION("PowerMac built-in audio driver."); diff --git a/sound/oss/dmasound/tas_common.c b/sound/oss/dmasound/tas_common.c index 665e85b..b295ef6 100644 --- a/sound/oss/dmasound/tas_common.c +++ b/sound/oss/dmasound/tas_common.c @@ -41,7 +41,6 @@ static u8 tas_i2c_address = 0x34; static struct i2c_client *tas_client; -static struct device_node* tas_node; static int tas_attach_adapter(struct i2c_adapter *); static int tas_detach_client(struct i2c_client *); @@ -190,17 +189,18 @@ tas_cleanup(void) int __init tas_init(int driver_id, const char *driver_name) { - u32* paddr; + const u32* paddr; + struct device_node *tas_node; printk(KERN_INFO "tas driver [%s])\n", driver_name); #ifndef CONFIG_I2C_POWERMAC request_module("i2c-powermac"); #endif - tas_node = find_devices("deq"); + tas_node = of_find_node_by_name("deq"); if (tas_node == NULL) return -ENODEV; - paddr = (u32 *)get_property(tas_node, "i2c-address", NULL); + paddr = of_get_property(tas_node, "i2c-address", NULL); if (paddr) { tas_i2c_address = (*paddr) >> 1; printk(KERN_INFO "using i2c address: 0x%x from device-tree\n", @@ -208,6 +208,7 @@ tas_init(int driver_id, const char *driver_name) } else printk(KERN_INFO "using i2c address: 0x%x (default)\n", tas_i2c_address); + of_node_put(tas_node); return i2c_add_driver(&tas_driver); } diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index c64af55..2bae9c1 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c @@ -816,6 +816,7 @@ static int snd_pmac_free(struct snd_pmac *chip) if (chip->pdev) pci_dev_put(chip->pdev); + of_node_put(chip->node); kfree(chip); return 0; } @@ -863,8 +864,10 @@ static void __init detect_byte_swap(struct snd_pmac *chip) */ static int __init snd_pmac_detect(struct snd_pmac *chip) { - struct device_node *sound = NULL; - unsigned int *prop, l; + struct device_node *sound; + struct device_node *dn; + const unsigned int *prop; + unsigned int l; struct macio_chip* macio; if (!machine_is(powermac)) @@ -890,22 +893,21 @@ static int __init snd_pmac_detect(struct snd_pmac *chip) else if (machine_is_compatible("PowerBook1,1") || machine_is_compatible("AAPL,PowerBook1998")) chip->is_pbook_G3 = 1; - chip->node = find_devices("awacs"); - if (chip->node) - sound = chip->node; + chip->node = of_find_node_by_name(NULL, "awacs"); + sound = of_node_get(chip->node); /* * powermac G3 models have a node called "davbus" * with a child called "sound". */ if (!chip->node) - chip->node = find_devices("davbus"); + chip->node = of_find_node_by_name(NULL, "davbus"); /* * if we didn't find a davbus device, try 'i2s-a' since * this seems to be what iBooks have */ if (! chip->node) { - chip->node = find_devices("i2s-a"); + chip->node = of_find_node_by_name(NULL, "i2s-a"); if (chip->node && chip->node->parent && chip->node->parent->parent) { if (device_is_compatible(chip->node->parent->parent, @@ -917,22 +919,25 @@ static int __init snd_pmac_detect(struct snd_pmac *chip) return -ENODEV; if (!sound) { - sound = find_devices("sound"); + sound = of_find_node_by_name(NULL, "sound"); while (sound && sound->parent != chip->node) - sound = sound->next; + sound = of_find_node_by_name(sound, "sound"); } - if (! sound) + if (! sound) { + of_node_put(chip->node); return -ENODEV; - prop = (unsigned int *) get_property(sound, "sub-frame", NULL); + } + prop = of_get_property(sound, "sub-frame", NULL); if (prop && *prop < 16) chip->subframe = *prop; - prop = (unsigned int *) get_property(sound, "layout-id", NULL); + prop = of_get_property(sound, "layout-id", NULL); if (prop) { /* partly deprecate snd-powermac, for those machines * that have a layout-id property for now */ printk(KERN_INFO "snd-powermac no longer handles any " "machines with a layout-id property " "in the device-tree, use snd-aoa.\n"); + of_node_put(chip->node); return -ENODEV; } /* This should be verified on older screamers */ @@ -967,10 +972,12 @@ static int __init snd_pmac_detect(struct snd_pmac *chip) chip->freq_table = tumbler_freqs; chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */ } - prop = (unsigned int *)get_property(sound, "device-id", NULL); + prop = of_get_property(sound, "device-id", NULL); if (prop) chip->device_id = *prop; - chip->has_iic = (find_devices("perch") != NULL); + dn = of_find_node_by_name(NULL, "perch"); + chip->has_iic = (dn != NULL); + of_node_put(dn); /* We need the PCI device for DMA allocations, let's use a crude method * for now ... @@ -997,10 +1004,9 @@ static int __init snd_pmac_detect(struct snd_pmac *chip) /* look for a property saying what sample rates are available */ - prop = (unsigned int *) get_property(sound, "sample-rates", &l); + prop = of_get_property(sound, "sample-rates", &l); if (! prop) - prop = (unsigned int *) get_property(sound, - "output-frame-rates", &l); + prop = of_get_property(sound, "output-frame-rates", &l); if (prop) { int i; chip->freqs_ok = 0; @@ -1021,6 +1027,7 @@ static int __init snd_pmac_detect(struct snd_pmac *chip) chip->freqs_ok = 1; } + of_node_put(sound); return 0; } diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c index 8f074c79..54e333f 100644 --- a/sound/ppc/tumbler.c +++ b/sound/ppc/tumbler.c @@ -1031,32 +1031,40 @@ static irqreturn_t headphone_intr(int irq, void *devid) /* look for audio-gpio device */ static struct device_node *find_audio_device(const char *name) { + struct device_node *gpiop; struct device_node *np; - if (! (np = find_devices("gpio"))) + gpiop = of_find_node_by_name(NULL, "gpio"); + if (! gpiop) return NULL; - for (np = np->child; np; np = np->sibling) { - const char *property = get_property(np, "audio-gpio", NULL); + for (np = of_get_next_child(gpiop, NULL); np; + np = of_get_next_child(gpiop, np)) { + const char *property = of_get_property(np, "audio-gpio", NULL); if (property && strcmp(property, name) == 0) - return np; + break; } - return NULL; + of_node_put(gpiop); + return np; } /* look for audio-gpio device */ static struct device_node *find_compatible_audio_device(const char *name) { + struct device_node *gpiop; struct device_node *np; - if (! (np = find_devices("gpio"))) + gpiop = of_find_node_by_name(NULL, "gpio"); + if (!gpiop) return NULL; - for (np = np->child; np; np = np->sibling) { + for (np = of_get_next_child(gpiop, NULL); np; + np = of_get_next_child(gpiop, np)) { if (device_is_compatible(np, name)) - return np; + break; } - return NULL; + of_node_put(gpiop); + return np; } /* find an audio device and get its address */ @@ -1066,6 +1074,7 @@ static long tumbler_find_device(const char *device, const char *platform, struct device_node *node; const u32 *base; u32 addr; + long ret; if (is_compatible) node = find_compatible_audio_device(device); @@ -1077,12 +1086,13 @@ static long tumbler_find_device(const char *device, const char *platform, return -ENODEV; } - base = get_property(node, "AAPL,address", NULL); + base = of_get_property(node, "AAPL,address", NULL); if (! base) { - base = get_property(node, "reg", NULL); + base = of_get_property(node, "reg", NULL); if (!base) { DBG("(E) cannot find address for device %s !\n", device); snd_printd("cannot find address for device %s\n", device); + of_node_put(node); return -ENODEV; } addr = *base; @@ -1093,7 +1103,7 @@ static long tumbler_find_device(const char *device, const char *platform, gp->addr = addr & 0x0000ffff; /* Try to find the active state, default to 0 ! */ - base = get_property(node, "audio-gpio-active-state", NULL); + base = of_get_property(node, "audio-gpio-active-state", NULL); if (base) { gp->active_state = *base; gp->active_val = (*base) ? 0x5 : 0x4; @@ -1108,7 +1118,7 @@ static long tumbler_find_device(const char *device, const char *platform, * as we don't yet have an interpreter for these things */ if (platform) - prop = get_property(node, platform, NULL); + prop = of_get_property(node, platform, NULL); if (prop) { if (prop[3] == 0x9 && prop[4] == 0x9) { gp->active_val = 0xd; @@ -1124,7 +1134,9 @@ static long tumbler_find_device(const char *device, const char *platform, DBG("(I) GPIO device %s found, offset: %x, active state: %d !\n", device, gp->addr, gp->active_state); - return irq_of_parse_and_map(node, 0); + ret = irq_of_parse_and_map(node, 0); + of_node_put(node); + return ret; } /* reset audio */ @@ -1310,7 +1322,7 @@ int __init snd_pmac_tumbler_init(struct snd_pmac *chip) { int i, err; struct pmac_tumbler *mix; - u32 *paddr; + const u32 *paddr; struct device_node *tas_node, *np; char *chipname; @@ -1331,9 +1343,9 @@ int __init snd_pmac_tumbler_init(struct snd_pmac *chip) for (np = chip->node->child; np; np = np->sibling) { if (!strcmp(np->name, "sound")) { - if (get_property(np, "has-anded-reset", NULL)) + if (of_get_property(np, "has-anded-reset", NULL)) mix->anded_reset = 1; - if (get_property(np, "layout-id", NULL)) + if (of_get_property(np, "layout-id", NULL)) mix->reset_on_sleep = 0; break; } @@ -1342,19 +1354,20 @@ int __init snd_pmac_tumbler_init(struct snd_pmac *chip) return err; /* set up TAS */ - tas_node = find_devices("deq"); + tas_node = of_find_node_by_name(NULL, "deq"); if (tas_node == NULL) - tas_node = find_devices("codec"); + tas_node = of_find_node_by_name(NULL, "codec"); if (tas_node == NULL) return -ENODEV; - paddr = (u32 *)get_property(tas_node, "i2c-address", NULL); + paddr = of_get_property(tas_node, "i2c-address", NULL); if (paddr == NULL) - paddr = (u32 *)get_property(tas_node, "reg", NULL); + paddr = of_get_property(tas_node, "reg", NULL); if (paddr) mix->i2c.addr = (*paddr) >> 1; else mix->i2c.addr = TAS_I2C_ADDR; + of_node_put(tas_node); DBG("(I) TAS i2c address is: %x\n", mix->i2c.addr); |