diff --git a/Documentation/ABI/removed/o2cb b/Documentation/ABI/removed/o2cb index 7f5daa465093b898f123b67fb4bc8ab453ce9bc0..20c91adca6d412102dabf73d6b6f387a60d888ec 100644 --- a/Documentation/ABI/removed/o2cb +++ b/Documentation/ABI/removed/o2cb @@ -1,6 +1,6 @@ What: /sys/o2cb symlink Date: May 2011 -KernelVersion: 2.6.40 +KernelVersion: 3.0 Contact: ocfs2-devel@oss.oracle.com Description: This is a symlink: /sys/o2cb to /sys/fs/o2cb. The symlink is removed when new versions of ocfs2-tools which know to look diff --git a/Documentation/ABI/removed/raw1394 b/Documentation/ABI/removed/raw1394 index 490aa1efc4ae613e3864329282f40b94789a663d..ec333e67632266a935daa6e2124744c09caa8d77 100644 --- a/Documentation/ABI/removed/raw1394 +++ b/Documentation/ABI/removed/raw1394 @@ -5,7 +5,7 @@ Description: /dev/raw1394 was a character device file that allowed low-level access to FireWire buses. Its major drawbacks were its inability to implement sensible device security policies, and its low level - of abstraction that required userspace clients do duplicate much + of abstraction that required userspace clients to duplicate much of the kernel's ieee1394 core functionality. Replaced by /dev/fw*, i.e. the ABI of firewire-core. diff --git a/Documentation/ABI/testing/debugfs-ideapad b/Documentation/ABI/testing/debugfs-ideapad new file mode 100644 index 0000000000000000000000000000000000000000..7079c0b21030f14f56896481bd436a96d241eb57 --- /dev/null +++ b/Documentation/ABI/testing/debugfs-ideapad @@ -0,0 +1,19 @@ +What: /sys/kernel/debug/ideapad/cfg +Date: Sep 2011 +KernelVersion: 3.2 +Contact: Ike Panhc +Description: + +cfg shows the return value of _CFG method in VPC2004 device. It tells machine +capability and what graphic component within the machine. + + +What: /sys/kernel/debug/ideapad/status +Date: Sep 2011 +KernelVersion: 3.2 +Contact: Ike Panhc +Description: + +status shows infos we can read and tells its meaning and value. + + diff --git a/Documentation/ABI/testing/evm b/Documentation/ABI/testing/evm new file mode 100644 index 0000000000000000000000000000000000000000..8374d4557e5dc0c3293775abaf369e92b91893a4 --- /dev/null +++ b/Documentation/ABI/testing/evm @@ -0,0 +1,23 @@ +What: security/evm +Date: March 2011 +Contact: Mimi Zohar +Description: + EVM protects a file's security extended attributes(xattrs) + against integrity attacks. The initial method maintains an + HMAC-sha1 value across the extended attributes, storing the + value as the extended attribute 'security.evm'. + + EVM depends on the Kernel Key Retention System to provide it + with a trusted/encrypted key for the HMAC-sha1 operation. + The key is loaded onto the root's keyring using keyctl. Until + EVM receives notification that the key has been successfully + loaded onto the keyring (echo 1 > /evm), EVM + can not create or validate the 'security.evm' xattr, but + returns INTEGRITY_UNKNOWN. Loading the key and signaling EVM + should be done as early as possible. Normally this is done + in the initramfs, which has already been measured as part + of the trusted boot. For more information on creating and + loading existing trusted/encrypted keys, refer to: + Documentation/keys-trusted-encrypted.txt. (A sample dracut + patch, which loads the trusted/encrypted key and enables + EVM, is available from http://linux-ima.sourceforge.net/#EVM.) diff --git a/Documentation/ABI/testing/sysfs-block b/Documentation/ABI/testing/sysfs-block index c1eb41cb9876083d3df79a6a995b692762acd21b..2b5d56127fce4d7f9a6f83b535cdfcf469f83e0b 100644 --- a/Documentation/ABI/testing/sysfs-block +++ b/Documentation/ABI/testing/sysfs-block @@ -206,3 +206,16 @@ Description: when a discarded area is read the discard_zeroes_data parameter will be set to one. Otherwise it will be 0 and the result of reading a discarded area is undefined. +What: /sys/block//alias +Date: Aug 2011 +Contact: Nao Nishijima +Description: + A raw device name of a disk does not always point a same disk + each boot-up time. Therefore, users have to use persistent + device names, which udev creates when the kernel finds a disk, + instead of raw device name. However, kernel doesn't show those + persistent names on its messages (e.g. dmesg). + This file can store an alias of the disk and it would be + appeared in kernel messages if it is set. A disk can have an + alias which length is up to 255bytes. Users can use alphabets, + numbers, "-" and "_" in alias name. This file is writeonce. diff --git a/Documentation/ABI/testing/sysfs-bus-bcma b/Documentation/ABI/testing/sysfs-bus-bcma index 06b62badddd18a4b5fdc61ae9012ad73621fcb7e..721b4aea3020a43f4722e61c6cff9cede284e664 100644 --- a/Documentation/ABI/testing/sysfs-bus-bcma +++ b/Documentation/ABI/testing/sysfs-bus-bcma @@ -1,6 +1,6 @@ What: /sys/bus/bcma/devices/.../manuf Date: May 2011 -KernelVersion: 2.6.40 +KernelVersion: 3.0 Contact: RafaÅ‚ MiÅ‚ecki Description: Each BCMA core has it's manufacturer id. See @@ -8,7 +8,7 @@ Description: What: /sys/bus/bcma/devices/.../id Date: May 2011 -KernelVersion: 2.6.40 +KernelVersion: 3.0 Contact: RafaÅ‚ MiÅ‚ecki Description: There are a few types of BCMA cores, they can be identified by @@ -16,7 +16,7 @@ Description: What: /sys/bus/bcma/devices/.../rev Date: May 2011 -KernelVersion: 2.6.40 +KernelVersion: 3.0 Contact: RafaÅ‚ MiÅ‚ecki Description: BCMA cores of the same type can still slightly differ depending @@ -24,7 +24,7 @@ Description: What: /sys/bus/bcma/devices/.../class Date: May 2011 -KernelVersion: 2.6.40 +KernelVersion: 3.0 Contact: RafaÅ‚ MiÅ‚ecki Description: Each BCMA core is identified by few fields, including class it diff --git a/Documentation/ABI/testing/sysfs-bus-pci-drivers-ehci_hcd b/Documentation/ABI/testing/sysfs-bus-pci-drivers-ehci_hcd new file mode 100644 index 0000000000000000000000000000000000000000..60c60fa624b2a063ea762d47f28b87847d041550 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-pci-drivers-ehci_hcd @@ -0,0 +1,46 @@ +What: /sys/bus/pci/drivers/ehci_hcd/.../companion + /sys/bus/usb/devices/usbN/../companion +Date: January 2007 +KernelVersion: 2.6.21 +Contact: Alan Stern +Description: + PCI-based EHCI USB controllers (i.e., high-speed USB-2.0 + controllers) are often implemented along with a set of + "companion" full/low-speed USB-1.1 controllers. When a + high-speed device is plugged in, the connection is routed + to the EHCI controller; when a full- or low-speed device + is plugged in, the connection is routed to the companion + controller. + + Sometimes you want to force a high-speed device to connect + at full speed, which can be accomplished by forcing the + connection to be routed to the companion controller. + That's what this file does. Writing a port number to the + file causes connections on that port to be routed to the + companion controller, and writing the negative of a port + number returns the port to normal operation. + + For example: To force the high-speed device attached to + port 4 on bus 2 to run at full speed: + + echo 4 >/sys/bus/usb/devices/usb2/../companion + + To return the port to high-speed operation: + + echo -4 >/sys/bus/usb/devices/usb2/../companion + + Reading the file gives the list of ports currently forced + to the companion controller. + + Note: Some EHCI controllers do not have companions; they + may contain an internal "transaction translator" or they + may be attached directly to a "rate-matching hub". This + mechanism will not work with such controllers. Also, it + cannot be used to force a port on a high-speed hub to + connect at full speed. + + Note: When this file was first added, it appeared in a + different sysfs directory. The location given above is + correct for 2.6.35 (and probably several earlier kernel + versions as well). + diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb index 294aa864a60a1d6056d2b5cf76536648f6d49567..e647378e9e88eaba8256af7b609cebc28d9506aa 100644 --- a/Documentation/ABI/testing/sysfs-bus-usb +++ b/Documentation/ABI/testing/sysfs-bus-usb @@ -142,3 +142,18 @@ Description: such devices. Users: usb_modeswitch + +What: /sys/bus/usb/devices/.../power/usb2_hardware_lpm +Date: September 2011 +Contact: Andiry Xu +Description: + If CONFIG_USB_SUSPEND is set and a USB 2.0 lpm-capable device + is plugged in to a xHCI host which support link PM, it will + perform a LPM test; if the test is passed and host supports + USB2 hardware LPM (xHCI 1.0 feature), USB2 hardware LPM will + be enabled for the device and the USB device directory will + contain a file named power/usb2_hardware_lpm. The file holds + a string value (enable or disable) indicating whether or not + USB2 hardware LPM is enabled for the device. Developer can + write y/Y/1 or n/N/0 to the file to enable/disable the + feature. diff --git a/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870 b/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870 index aa11dbdd794b2e1725bc254651198fa1af938f35..4a9c545bda4ba2d4d75637290007d2b510134c9f 100644 --- a/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870 +++ b/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870 @@ -4,8 +4,8 @@ What: /sys/class/backlight//l2_bright_max What: /sys/class/backlight//l3_office_max What: /sys/class/backlight//l4_indoor_max What: /sys/class/backlight//l5_dark_max -Date: Mai 2011 -KernelVersion: 2.6.40 +Date: May 2011 +KernelVersion: 3.0 Contact: device-drivers-devel@blackfin.uclinux.org Description: Control the maximum brightness for @@ -18,8 +18,8 @@ What: /sys/class/backlight//l2_bright_dim What: /sys/class/backlight//l3_office_dim What: /sys/class/backlight//l4_indoor_dim What: /sys/class/backlight//l5_dark_dim -Date: Mai 2011 -KernelVersion: 2.6.40 +Date: May 2011 +KernelVersion: 3.0 Contact: device-drivers-devel@blackfin.uclinux.org Description: Control the dim brightness for @@ -29,8 +29,8 @@ Description: this . What: /sys/class/backlight//ambient_light_level -Date: Mai 2011 -KernelVersion: 2.6.40 +Date: May 2011 +KernelVersion: 3.0 Contact: device-drivers-devel@blackfin.uclinux.org Description: Get conversion value of the light sensor. @@ -39,8 +39,8 @@ Description: 8000 (max ambient brightness) What: /sys/class/backlight//ambient_light_zone -Date: Mai 2011 -KernelVersion: 2.6.40 +Date: May 2011 +KernelVersion: 3.0 Contact: device-drivers-devel@blackfin.uclinux.org Description: Get/Set current ambient light zone. Reading returns diff --git a/Documentation/ABI/testing/sysfs-class-devfreq b/Documentation/ABI/testing/sysfs-class-devfreq new file mode 100644 index 0000000000000000000000000000000000000000..23d78b5aab11d140f1f47e29c098d44051793ef8 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-devfreq @@ -0,0 +1,52 @@ +What: /sys/class/devfreq/.../ +Date: September 2011 +Contact: MyungJoo Ham +Description: + Provide a place in sysfs for the devfreq objects. + This allows accessing various devfreq specific variables. + The name of devfreq object denoted as ... is same as the + name of device using devfreq. + +What: /sys/class/devfreq/.../governor +Date: September 2011 +Contact: MyungJoo Ham +Description: + The /sys/class/devfreq/.../governor shows the name of the + governor used by the corresponding devfreq object. + +What: /sys/class/devfreq/.../cur_freq +Date: September 2011 +Contact: MyungJoo Ham +Description: + The /sys/class/devfreq/.../cur_freq shows the current + frequency of the corresponding devfreq object. + +What: /sys/class/devfreq/.../central_polling +Date: September 2011 +Contact: MyungJoo Ham +Description: + The /sys/class/devfreq/.../central_polling shows whether + the devfreq ojbect is using devfreq-provided central + polling mechanism or not. + +What: /sys/class/devfreq/.../polling_interval +Date: September 2011 +Contact: MyungJoo Ham +Description: + The /sys/class/devfreq/.../polling_interval shows and sets + the requested polling interval of the corresponding devfreq + object. The values are represented in ms. If the value is + less than 1 jiffy, it is considered to be 0, which means + no polling. This value is meaningless if the governor is + not polling; thus. If the governor is not using + devfreq-provided central polling + (/sys/class/devfreq/.../central_polling is 0), this value + may be useless. + +What: /sys/class/devfreq/.../userspace/set_freq +Date: September 2011 +Contact: MyungJoo Ham +Description: + The /sys/class/devfreq/.../userspace/set_freq shows and + sets the requested frequency for the devfreq object if + userspace governor is in effect. diff --git a/Documentation/ABI/testing/sysfs-class-net-mesh b/Documentation/ABI/testing/sysfs-class-net-mesh index 748fe1701d25a1c5e2f23d9710007423f99fb8a9..b02001488eef3d37869c53693b088de6433e2900 100644 --- a/Documentation/ABI/testing/sysfs-class-net-mesh +++ b/Documentation/ABI/testing/sysfs-class-net-mesh @@ -22,6 +22,14 @@ Description: mesh will be fragmented or silently discarded if the packet size exceeds the outgoing interface MTU. +What: /sys/class/net//mesh/ap_isolation +Date: May 2011 +Contact: Antonio Quartulli +Description: + Indicates whether the data traffic going from a + wireless client to another wireless client will be + silently dropped. + What: /sys/class/net//mesh/gw_bandwidth Date: October 2010 Contact: Marek Lindner diff --git a/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff b/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff new file mode 100644 index 0000000000000000000000000000000000000000..9aec8ef228b0111ac84c566d39bcaccce19f46eb --- /dev/null +++ b/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff @@ -0,0 +1,7 @@ +What: /sys/module/hid_logitech/drivers/hid:logitech//range. +Date: July 2011 +KernelVersion: 3.2 +Contact: Michal Malý +Description: Display minimum, maximum and current range of the steering + wheel. Writing a value within min and max boundaries sets the + range of the wheel. diff --git a/Documentation/ABI/testing/sysfs-driver-wacom b/Documentation/ABI/testing/sysfs-driver-wacom new file mode 100644 index 0000000000000000000000000000000000000000..82d4df136444fb4e8d1d273fe08cb12fb2d2c18b --- /dev/null +++ b/Documentation/ABI/testing/sysfs-driver-wacom @@ -0,0 +1,72 @@ +What: /sys/class/hidraw/hidraw*/device/speed +Date: April 2010 +Kernel Version: 2.6.35 +Contact: linux-bluetooth@vger.kernel.org +Description: + The /sys/class/hidraw/hidraw*/device/speed file controls + reporting speed of Wacom bluetooth tablet. Reading from + this file returns 1 if tablet reports in high speed mode + or 0 otherwise. Writing to this file one of these values + switches reporting speed. + +What: /sys/bus/usb/devices/-:./wacom_led/led +Date: August 2011 +Contact: linux-input@vger.kernel.org +Description: + Attribute group for control of the status LEDs and the OLEDs. + This attribute group is only available for Intuos 4 M, L, + and XL (with LEDs and OLEDs) and Cintiq 21UX2 (LEDs only). + Therefore its presence implicitly signifies the presence of + said LEDs and OLEDs on the tablet device. + +What: /sys/bus/usb/devices/-:./wacom_led/status0_luminance +Date: August 2011 +Contact: linux-input@vger.kernel.org +Description: + Writing to this file sets the status LED luminance (1..127) + when the stylus does not touch the tablet surface, and no + button is pressed on the stylus. This luminance level is + normally lower than the level when a button is pressed. + +What: /sys/bus/usb/devices/-:./wacom_led/status1_luminance +Date: August 2011 +Contact: linux-input@vger.kernel.org +Description: + Writing to this file sets the status LED luminance (1..127) + when the stylus touches the tablet surface, or any button is + pressed on the stylus. + +What: /sys/bus/usb/devices/-:./wacom_led/status_led0_select +Date: August 2011 +Contact: linux-input@vger.kernel.org +Description: + Writing to this file sets which one of the four (for Intuos 4) + or of the right four (for Cintiq 21UX2) status LEDs is active (0..3). + The other three LEDs on the same side are always inactive. + +What: /sys/bus/usb/devices/-:./wacom_led/status_led1_select +Date: September 2011 +Contact: linux-input@vger.kernel.org +Description: + Writing to this file sets which one of the left four (for Cintiq 21UX2) + status LEDs is active (0..3). The other three LEDs on the left are always + inactive. + +What: /sys/bus/usb/devices/-:./wacom_led/buttons_luminance +Date: August 2011 +Contact: linux-input@vger.kernel.org +Description: + Writing to this file sets the overall luminance level (0..15) + of all eight button OLED displays. + +What: /sys/bus/usb/devices/-:./wacom_led/button_rawimg +Date: August 2011 +Contact: linux-input@vger.kernel.org +Description: + When writing a 1024 byte raw image in Wacom Intuos 4 + interleaving format to the file, the image shows up on Button N + of the device. The image is a 64x32 pixel 4-bit gray image. The + 1024 byte binary is split up into 16x 64 byte chunks. Each 64 + byte chunk encodes the image data for two consecutive lines on + the display. The low nibble of each byte contains the first + line, and the high nibble contains the second line. diff --git a/Documentation/ABI/testing/sysfs-platform-ideapad-laptop b/Documentation/ABI/testing/sysfs-platform-ideapad-laptop index ff53183c3848d20ea357c276fb1bf930693cbd5c..814b01354c414caf71337d115b41fc92c89769b8 100644 --- a/Documentation/ABI/testing/sysfs-platform-ideapad-laptop +++ b/Documentation/ABI/testing/sysfs-platform-ideapad-laptop @@ -5,19 +5,4 @@ Contact: "Ike Panhc " Description: Control the power of camera module. 1 means on, 0 means off. -What: /sys/devices/platform/ideapad/cfg -Date: Jun 2011 -KernelVersion: 3.1 -Contact: "Ike Panhc " -Description: - Ideapad capability bits. - Bit 8-10: 1 - Intel graphic only - 2 - ATI graphic only - 3 - Nvidia graphic only - 4 - Intel and ATI graphic - 5 - Intel and Nvidia graphic - Bit 16: Bluetooth exist (1 for exist) - Bit 17: 3G exist (1 for exist) - Bit 18: Wifi exist (1 for exist) - Bit 19: Camera exist (1 for exist) diff --git a/Documentation/ABI/testing/sysfs-wacom b/Documentation/ABI/testing/sysfs-wacom deleted file mode 100644 index 1517976e25c4648dd6174dbd04e4fea8bd6ff6d9..0000000000000000000000000000000000000000 --- a/Documentation/ABI/testing/sysfs-wacom +++ /dev/null @@ -1,10 +0,0 @@ -What: /sys/class/hidraw/hidraw*/device/speed -Date: April 2010 -Kernel Version: 2.6.35 -Contact: linux-bluetooth@vger.kernel.org -Description: - The /sys/class/hidraw/hidraw*/device/speed file controls - reporting speed of wacom bluetooth tablet. Reading from - this file returns 1 if tablet reports in high speed mode - or 0 otherwise. Writing to this file one of these values - switches reporting speed. diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl index 445289cd0e65fb855b66e6967af1de961f5ba2d3..2014155c899d00c7da58f3fbab2409dc2880d139 100644 --- a/Documentation/DocBook/80211.tmpl +++ b/Documentation/DocBook/80211.tmpl @@ -433,8 +433,18 @@ Insert notes about VLAN interfaces with hw crypto here or in the hw crypto chapter. +
+ support for powersaving clients +!Pinclude/net/mac80211.h AP support for powersaving clients +
!Finclude/net/mac80211.h ieee80211_get_buffered_bc !Finclude/net/mac80211.h ieee80211_beacon_get +!Finclude/net/mac80211.h ieee80211_sta_eosp_irqsafe +!Finclude/net/mac80211.h ieee80211_frame_release_type +!Finclude/net/mac80211.h ieee80211_sta_ps_transition +!Finclude/net/mac80211.h ieee80211_sta_ps_transition_ni +!Finclude/net/mac80211.h ieee80211_sta_set_buffered +!Finclude/net/mac80211.h ieee80211_sta_block_awake @@ -460,7 +470,6 @@ !Finclude/net/mac80211.h sta_notify_cmd !Finclude/net/mac80211.h ieee80211_find_sta !Finclude/net/mac80211.h ieee80211_find_sta_by_ifaddr -!Finclude/net/mac80211.h ieee80211_sta_block_awake diff --git a/Documentation/DocBook/media/dvb/dvbproperty.xml b/Documentation/DocBook/media/dvb/dvbproperty.xml index 207e1a5bf8f027d8ae073fdabe107a8741598494..3bc8a61efe301a4b32bd89862efd28219e9315c4 100644 --- a/Documentation/DocBook/media/dvb/dvbproperty.xml +++ b/Documentation/DocBook/media/dvb/dvbproperty.xml @@ -352,6 +352,7 @@ typedef enum fe_delivery_system { SYS_CMMB, SYS_DAB, SYS_DVBT2, + SYS_TURBO, } fe_delivery_system_t; @@ -809,6 +810,8 @@ typedef enum fe_hierarchy { DTV_INVERSION DTV_SYMBOL_RATE DTV_INNER_FEC + DTV_VOLTAGE + DTV_TONE Future implementations might add those two missing parameters: @@ -818,25 +821,18 @@ typedef enum fe_hierarchy {
DVB-S2 delivery system - The following parameters are valid for DVB-S2: + In addition to all parameters valid for DVB-S, DVB-S2 supports the following parameters: - DTV_API_VERSION - DTV_DELIVERY_SYSTEM - DTV_TUNE - DTV_CLEAR - DTV_FREQUENCY - DTV_INVERSION - DTV_SYMBOL_RATE - DTV_INNER_FEC - DTV_VOLTAGE - DTV_TONE + DTV_MODULATION DTV_PILOT DTV_ROLLOFF - Future implementations might add those two missing parameters: +
+
+ Turbo code delivery system + In addition to all parameters valid for DVB-S, turbo code supports the following parameters: - DTV_DISEQC_MASTER - DTV_DISEQC_SLAVE_REPLY + DTV_MODULATION
diff --git a/Documentation/DocBook/media/dvb/intro.xml b/Documentation/DocBook/media/dvb/intro.xml index c75dc7cc3e9b6ec167b7fa7091532df7aeac4bd6..170064a3dc8f4b3db90bb348331ec777074f84c2 100644 --- a/Documentation/DocBook/media/dvb/intro.xml +++ b/Documentation/DocBook/media/dvb/intro.xml @@ -205,7 +205,7 @@ a partial path like: additional include file linux/dvb/version.h exists, which defines the constant DVB_API_VERSION. This document -describes DVB_API_VERSION 3. +describes DVB_API_VERSION 5.4.
diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml index ce1004a7da5233f96d1a33636a11b24879ae69a1..91410b6e7e08cf6a3eaabb036fb3e90c4983f6e2 100644 --- a/Documentation/DocBook/media/v4l/compat.xml +++ b/Documentation/DocBook/media/v4l/compat.xml @@ -2370,6 +2370,14 @@ that used it. It was originally scheduled for removal in 2.6.35. +
+ V4L2 in Linux 3.2 + + + V4L2_CTRL_FLAG_VOLATILE was added to signal volatile controls to userspace. + + +
Relation of V4L2 to other Linux multimedia APIs diff --git a/Documentation/DocBook/media/v4l/dev-subdev.xml b/Documentation/DocBook/media/v4l/dev-subdev.xml index 05c8fefcbcbe91fd01169472ee6fac5d6dbd8ab3..0916a7343a166b007f94da88fe8179b872b8be3b 100644 --- a/Documentation/DocBook/media/v4l/dev-subdev.xml +++ b/Documentation/DocBook/media/v4l/dev-subdev.xml @@ -266,7 +266,7 @@ When satisfied with the try results, applications can set the active formats by setting the which argument to - V4L2_SUBDEV_FORMAT_TRY. Active formats are changed + V4L2_SUBDEV_FORMAT_ACTIVE. Active formats are changed exactly as try formats by drivers. To avoid modifying the hardware state during format negotiation, applications should negotiate try formats first and then modify the active settings using the try formats returned during diff --git a/Documentation/DocBook/media/v4l/v4l2.xml b/Documentation/DocBook/media/v4l/v4l2.xml index 0d05e8747c12e24da9a2a4cebcdce4826e0858a4..40132c2776476a582bdf0eff818fc81c5f007c0f 100644 --- a/Documentation/DocBook/media/v4l/v4l2.xml +++ b/Documentation/DocBook/media/v4l/v4l2.xml @@ -127,6 +127,13 @@ structs, ioctls) must be noted in more detail in the history chapter (compat.xml), along with the possible impact on existing drivers and applications. --> + + 3.2 + 2011-08-26 + hv + Added V4L2_CTRL_FLAG_VOLATILE. + + 3.1 2011-06-27 @@ -410,7 +417,7 @@ and discussions on the V4L mailing list. Video for Linux Two API Specification - Revision 3.1 + Revision 3.2 &sub-common; diff --git a/Documentation/DocBook/media/v4l/vidioc-dqevent.xml b/Documentation/DocBook/media/v4l/vidioc-dqevent.xml index 7769642ee431b11a83d423d260ea8ed1e87e66aa..e8714aa1643343de973e32f5abfa5e331b26bb7d 100644 --- a/Documentation/DocBook/media/v4l/vidioc-dqevent.xml +++ b/Documentation/DocBook/media/v4l/vidioc-dqevent.xml @@ -86,6 +86,12 @@ Event data for event V4L2_EVENT_CTRL. + + + &v4l2-event-frame-sync; + frame + Event data for event V4L2_EVENT_FRAME_SYNC. + __u8 @@ -135,6 +141,129 @@ + + struct <structname>v4l2_event_vsync</structname> + + &cs-str; + + + __u8 + field + The upcoming field. See &v4l2-field;. + + + +
+ + + struct <structname>v4l2_event_ctrl</structname> + + &cs-str; + + + __u32 + changes + + A bitmask that tells what has changed. See . + + + __u32 + type + + The type of the control. See &v4l2-ctrl-type;. + + + union (anonymous) + + + + + + + __s32 + value + The 32-bit value of the control for 32-bit control types. + This is 0 for string controls since the value of a string + cannot be passed using &VIDIOC-DQEVENT;. + + + + __s64 + value64 + The 64-bit value of the control for 64-bit control types. + + + __u32 + flags + + The control flags. See . + + + __s32 + minimum + + The minimum value of the control. See &v4l2-queryctrl;. + + + __s32 + maximum + + The maximum value of the control. See &v4l2-queryctrl;. + + + __s32 + step + + The step value of the control. See &v4l2-queryctrl;. + + + __s32 + default_value + + The default value value of the control. See &v4l2-queryctrl;. + + + +
+ + + struct <structname>v4l2_event_frame_sync</structname> + + &cs-str; + + + __u32 + frame_sequence + + The sequence number of the frame being received. + + + + +
+ + + Changes + + &cs-def; + + + V4L2_EVENT_CTRL_CH_VALUE + 0x0001 + This control event was triggered because the value of the control + changed. Special case: if a button control is pressed, then this + event is sent as well, even though there is not explicit value + associated with a button control. + + + V4L2_EVENT_CTRL_CH_FLAGS + 0x0002 + This control event was triggered because the control flags + changed. + + + +
&return-value; diff --git a/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml b/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml index 677ea646c29fc71c6d8b9970cbb230d1784a46d1..0ac0057a51c4c9cb47da092159b955eb1ff11ad9 100644 --- a/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml +++ b/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml @@ -406,6 +406,15 @@ flag is typically present for relative controls or action controls where writing a value will cause the device to carry out a given action (⪚ motor control) but no meaningful value can be returned.
+ + V4L2_CTRL_FLAG_VOLATILE + 0x0080 + This control is volatile, which means that the value of the control +changes continuously. A typical example would be the current gain value if the device +is in auto-gain mode. In such a case the hardware calculates the gain value based on +the lighting conditions which can change over time. Note that setting a new value for +a volatile control will have no effect. The new value will just be ignored. + diff --git a/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml b/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml index 69c0d8a2a3d2dd812847a30d59969209d8917127..5c70b616d8185c0645044b0e270398932a0d28c9 100644 --- a/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml +++ b/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml @@ -138,6 +138,22 @@ field of the oldest event.
+ + V4L2_EVENT_FRAME_SYNC + 4 + + Triggered immediately when the reception of a + frame has begun. This event has a + &v4l2-event-frame-sync; associated with it. + + If the hardware needs to be stopped in the case of a + buffer underrun it might not be able to generate this event. + In such cases the frame_sequence + field in &v4l2-event-frame-sync; will not be incremented. This + causes two consecutive frame sequence numbers to have n times + frame interval in between them. + + V4L2_EVENT_PRIVATE_START 0x08000000 @@ -183,113 +199,6 @@ - - struct <structname>v4l2_event_vsync</structname> - - &cs-str; - - - __u8 - field - The upcoming field. See &v4l2-field;. - - - -
- - - struct <structname>v4l2_event_ctrl</structname> - - &cs-str; - - - __u32 - changes - - A bitmask that tells what has changed. See . - - - __u32 - type - - The type of the control. See &v4l2-ctrl-type;. - - - union (anonymous) - - - - - - - __s32 - value - The 32-bit value of the control for 32-bit control types. - This is 0 for string controls since the value of a string - cannot be passed using &VIDIOC-DQEVENT;. - - - - __s64 - value64 - The 64-bit value of the control for 64-bit control types. - - - __u32 - flags - - The control flags. See . - - - __s32 - minimum - - The minimum value of the control. See &v4l2-queryctrl;. - - - __s32 - maximum - - The maximum value of the control. See &v4l2-queryctrl;. - - - __s32 - step - - The step value of the control. See &v4l2-queryctrl;. - - - __s32 - default_value - - The default value value of the control. See &v4l2-queryctrl;. - - - -
- - - Changes - - &cs-def; - - - V4L2_EVENT_CTRL_CH_VALUE - 0x0001 - This control event was triggered because the value of the control - changed. Special case: if a button control is pressed, then this - event is sent as well, even though there is not explicit value - associated with a button control. - - - V4L2_EVENT_CTRL_CH_FLAGS - 0x0002 - This control event was triggered because the control flags - changed. - - - -
&return-value; diff --git a/Documentation/DocBook/uio-howto.tmpl b/Documentation/DocBook/uio-howto.tmpl index 7c4b514d62b1f705a8424e36e1b1ab1ebdca7d93..54883de5d5f9b598ab981de82269c908dec86114 100644 --- a/Documentation/DocBook/uio-howto.tmpl +++ b/Documentation/DocBook/uio-howto.tmpl @@ -529,7 +529,7 @@ memory (e.g. allocated with kmalloc()). There's also -unsigned long addr: Required if the mapping is used. +phys_addr_t addr: Required if the mapping is used. Fill in the address of your memory block. This address is the one that appears in sysfs. diff --git a/Documentation/DocBook/writing-an-alsa-driver.tmpl b/Documentation/DocBook/writing-an-alsa-driver.tmpl index 598c22f3b3ac8f755b1595442698f9fc9294802a..5de23c00707828100ce750260ec71e727567d828 100644 --- a/Documentation/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/DocBook/writing-an-alsa-driver.tmpl @@ -4288,7 +4288,7 @@ struct _snd_pcm_runtime { @@ -4343,6 +4343,13 @@ struct _snd_pcm_runtime { by itself to start processing the output stream in the irq handler. + + If the MPU-401 interface shares its interrupt with the other logical + devices on the card, set MPU401_INFO_IRQ_HOOK + (see + below). + + Usually, the port address corresponds to the command port and port + 1 corresponds to the data port. If not, you may change @@ -4375,14 +4382,12 @@ struct _snd_pcm_runtime { - The 6th argument specifies the irq number for UART. If the irq - is already allocated, pass 0 to the 7th argument - (irq_flags). Otherwise, pass the flags - for irq allocation - (SA_XXX bits) to it, and the irq will be - reserved by the mpu401-uart layer. If the card doesn't generate - UART interrupts, pass -1 as the irq number. Then a timer - interrupt will be invoked for polling. + The 6th argument specifies the ISA irq number that will be + allocated. If no interrupt is to be allocated (because your + code is already allocating a shared interrupt, or because the + device does not use interrupts), pass -1 instead. + For a MPU-401 device without an interrupt, a polling timer + will be used instead.
@@ -4390,12 +4395,13 @@ struct _snd_pcm_runtime { Interrupt Handler When the interrupt is allocated in - snd_mpu401_uart_new(), the private - interrupt handler is used, hence you don't have anything else to do - than creating the mpu401 stuff. Otherwise, you have to call - snd_mpu401_uart_interrupt() explicitly when - a UART interrupt is invoked and checked in your own interrupt - handler. + snd_mpu401_uart_new(), an exclusive ISA + interrupt handler is automatically used, hence you don't have + anything else to do than creating the mpu401 stuff. Otherwise, you + have to set MPU401_INFO_IRQ_HOOK, and call + snd_mpu401_uart_interrupt() explicitly from your + own interrupt handler when it has determined that a UART interrupt + has occurred. diff --git a/Documentation/PCI/pci.txt b/Documentation/PCI/pci.txt index 6148d4080f888a9967492717b2837bbbb0b56970..aa09e5476bba2c1a6ff53223312bc8d11ed23aea 100644 --- a/Documentation/PCI/pci.txt +++ b/Documentation/PCI/pci.txt @@ -314,7 +314,7 @@ from the PCI device config space. Use the values in the pci_dev structure as the PCI "bus address" might have been remapped to a "host physical" address by the arch/chip-set specific kernel support. -See Documentation/IO-mapping.txt for how to access device registers +See Documentation/io-mapping.txt for how to access device registers or device memory. The device driver needs to call pci_request_region() to verify diff --git a/Documentation/RCU/NMI-RCU.txt b/Documentation/RCU/NMI-RCU.txt index bf82851a0e576e501137090a6550cee82f8cc3bb..687777f83b2371d4bd24e5d7abff88d7cf90a5d8 100644 --- a/Documentation/RCU/NMI-RCU.txt +++ b/Documentation/RCU/NMI-RCU.txt @@ -95,7 +95,7 @@ not to return until all ongoing NMI handlers exit. It is therefore safe to free up the handler's data as soon as synchronize_sched() returns. Important note: for this to work, the architecture in question must -invoke irq_enter() and irq_exit() on NMI entry and exit, respectively. +invoke nmi_enter() and nmi_exit() on NMI entry and exit, respectively. Answer to Quick Quiz diff --git a/Documentation/RCU/lockdep-splat.txt b/Documentation/RCU/lockdep-splat.txt new file mode 100644 index 0000000000000000000000000000000000000000..bf9061142827fca8d7f19c6cb013f322b47bc4e2 --- /dev/null +++ b/Documentation/RCU/lockdep-splat.txt @@ -0,0 +1,110 @@ +Lockdep-RCU was added to the Linux kernel in early 2010 +(http://lwn.net/Articles/371986/). This facility checks for some common +misuses of the RCU API, most notably using one of the rcu_dereference() +family to access an RCU-protected pointer without the proper protection. +When such misuse is detected, an lockdep-RCU splat is emitted. + +The usual cause of a lockdep-RCU slat is someone accessing an +RCU-protected data structure without either (1) being in the right kind of +RCU read-side critical section or (2) holding the right update-side lock. +This problem can therefore be serious: it might result in random memory +overwriting or worse. There can of course be false positives, this +being the real world and all that. + +So let's look at an example RCU lockdep splat from 3.0-rc5, one that +has long since been fixed: + +=============================== +[ INFO: suspicious RCU usage. ] +------------------------------- +block/cfq-iosched.c:2776 suspicious rcu_dereference_protected() usage! + +other info that might help us debug this: + + +rcu_scheduler_active = 1, debug_locks = 0 +3 locks held by scsi_scan_6/1552: + #0: (&shost->scan_mutex){+.+.+.}, at: [] +scsi_scan_host_selected+0x5a/0x150 + #1: (&eq->sysfs_lock){+.+...}, at: [] +elevator_exit+0x22/0x60 + #2: (&(&q->__queue_lock)->rlock){-.-...}, at: [] +cfq_exit_queue+0x43/0x190 + +stack backtrace: +Pid: 1552, comm: scsi_scan_6 Not tainted 3.0.0-rc5 #17 +Call Trace: + [] lockdep_rcu_dereference+0xbb/0xc0 + [] __cfq_exit_single_io_context+0xe9/0x120 + [] cfq_exit_queue+0x7c/0x190 + [] elevator_exit+0x36/0x60 + [] blk_cleanup_queue+0x4a/0x60 + [] scsi_free_queue+0x9/0x10 + [] __scsi_remove_device+0x84/0xd0 + [] scsi_probe_and_add_lun+0x353/0xb10 + [] ? error_exit+0x29/0xb0 + [] ? _raw_spin_unlock_irqrestore+0x3d/0x80 + [] __scsi_scan_target+0x112/0x680 + [] ? trace_hardirqs_off_thunk+0x3a/0x3c + [] ? error_exit+0x29/0xb0 + [] ? kobject_del+0x40/0x40 + [] scsi_scan_channel+0x86/0xb0 + [] scsi_scan_host_selected+0x140/0x150 + [] do_scsi_scan_host+0x89/0x90 + [] do_scan_async+0x20/0x160 + [] ? do_scsi_scan_host+0x90/0x90 + [] kthread+0xa6/0xb0 + [] kernel_thread_helper+0x4/0x10 + [] ? finish_task_switch+0x80/0x110 + [] ? retint_restore_args+0xe/0xe + [] ? __init_kthread_worker+0x70/0x70 + [] ? gs_change+0xb/0xb + +Line 2776 of block/cfq-iosched.c in v3.0-rc5 is as follows: + + if (rcu_dereference(ioc->ioc_data) == cic) { + +This form says that it must be in a plain vanilla RCU read-side critical +section, but the "other info" list above shows that this is not the +case. Instead, we hold three locks, one of which might be RCU related. +And maybe that lock really does protect this reference. If so, the fix +is to inform RCU, perhaps by changing __cfq_exit_single_io_context() to +take the struct request_queue "q" from cfq_exit_queue() as an argument, +which would permit us to invoke rcu_dereference_protected as follows: + + if (rcu_dereference_protected(ioc->ioc_data, + lockdep_is_held(&q->queue_lock)) == cic) { + +With this change, there would be no lockdep-RCU splat emitted if this +code was invoked either from within an RCU read-side critical section +or with the ->queue_lock held. In particular, this would have suppressed +the above lockdep-RCU splat because ->queue_lock is held (see #2 in the +list above). + +On the other hand, perhaps we really do need an RCU read-side critical +section. In this case, the critical section must span the use of the +return value from rcu_dereference(), or at least until there is some +reference count incremented or some such. One way to handle this is to +add rcu_read_lock() and rcu_read_unlock() as follows: + + rcu_read_lock(); + if (rcu_dereference(ioc->ioc_data) == cic) { + spin_lock(&ioc->lock); + rcu_assign_pointer(ioc->ioc_data, NULL); + spin_unlock(&ioc->lock); + } + rcu_read_unlock(); + +With this change, the rcu_dereference() is always within an RCU +read-side critical section, which again would have suppressed the +above lockdep-RCU splat. + +But in this particular case, we don't actually deference the pointer +returned from rcu_dereference(). Instead, that pointer is just compared +to the cic pointer, which means that the rcu_dereference() can be replaced +by rcu_access_pointer() as follows: + + if (rcu_access_pointer(ioc->ioc_data) == cic) { + +Because it is legal to invoke rcu_access_pointer() without protection, +this change would also suppress the above lockdep-RCU splat. diff --git a/Documentation/RCU/lockdep.txt b/Documentation/RCU/lockdep.txt index d7a49b2f6994c68ced38075000ccbc07803ba413..a102d4b3724bad454250d5d9e4ae883818725d91 100644 --- a/Documentation/RCU/lockdep.txt +++ b/Documentation/RCU/lockdep.txt @@ -32,9 +32,27 @@ checking of rcu_dereference() primitives: srcu_dereference(p, sp): Check for SRCU read-side critical section. rcu_dereference_check(p, c): - Use explicit check expression "c". This is useful in - code that is invoked by both readers and updaters. - rcu_dereference_raw(p) + Use explicit check expression "c" along with + rcu_read_lock_held(). This is useful in code that is + invoked by both RCU readers and updaters. + rcu_dereference_bh_check(p, c): + Use explicit check expression "c" along with + rcu_read_lock_bh_held(). This is useful in code that + is invoked by both RCU-bh readers and updaters. + rcu_dereference_sched_check(p, c): + Use explicit check expression "c" along with + rcu_read_lock_sched_held(). This is useful in code that + is invoked by both RCU-sched readers and updaters. + srcu_dereference_check(p, c): + Use explicit check expression "c" along with + srcu_read_lock_held()(). This is useful in code that + is invoked by both SRCU readers and updaters. + rcu_dereference_index_check(p, c): + Use explicit check expression "c", but the caller + must supply one of the rcu_read_lock_held() functions. + This is useful in code that uses RCU-protected arrays + that is invoked by both RCU readers and updaters. + rcu_dereference_raw(p): Don't check. (Use sparingly, if at all.) rcu_dereference_protected(p, c): Use explicit check expression "c", and omit all barriers @@ -48,13 +66,11 @@ checking of rcu_dereference() primitives: value of the pointer itself, for example, against NULL. The rcu_dereference_check() check expression can be any boolean -expression, but would normally include one of the rcu_read_lock_held() -family of functions and a lockdep expression. However, any boolean -expression can be used. For a moderately ornate example, consider -the following: +expression, but would normally include a lockdep expression. However, +any boolean expression can be used. For a moderately ornate example, +consider the following: file = rcu_dereference_check(fdt->fd[fd], - rcu_read_lock_held() || lockdep_is_held(&files->file_lock) || atomic_read(&files->count) == 1); @@ -62,7 +78,7 @@ This expression picks up the pointer "fdt->fd[fd]" in an RCU-safe manner, and, if CONFIG_PROVE_RCU is configured, verifies that this expression is used in: -1. An RCU read-side critical section, or +1. An RCU read-side critical section (implicit), or 2. with files->file_lock held, or 3. on an unshared files_struct. diff --git a/Documentation/RCU/torture.txt b/Documentation/RCU/torture.txt index 5d9016795fd825a43f2a4093e4edd870cb92e42c..783d6c134d3f007c220ca6a24203b1a16ea136c2 100644 --- a/Documentation/RCU/torture.txt +++ b/Documentation/RCU/torture.txt @@ -42,7 +42,7 @@ fqs_holdoff Holdoff time (in microseconds) between consecutive calls fqs_stutter Wait time (in seconds) between consecutive bursts of calls to force_quiescent_state(). -irqreaders Says to invoke RCU readers from irq level. This is currently +irqreader Says to invoke RCU readers from irq level. This is currently done via timers. Defaults to "1" for variants of RCU that permit this. (Or, more accurately, variants of RCU that do -not- permit this know to ignore this variable.) @@ -79,19 +79,68 @@ stutter The length of time to run the test before pausing for this Specifying "stutter=0" causes the test to run continuously without pausing, which is the old default behavior. +test_boost Whether or not to test the ability of RCU to do priority + boosting. Defaults to "test_boost=1", which performs + RCU priority-inversion testing only if the selected + RCU implementation supports priority boosting. Specifying + "test_boost=0" never performs RCU priority-inversion + testing. Specifying "test_boost=2" performs RCU + priority-inversion testing even if the selected RCU + implementation does not support RCU priority boosting, + which can be used to test rcutorture's ability to + carry out RCU priority-inversion testing. + +test_boost_interval + The number of seconds in an RCU priority-inversion test + cycle. Defaults to "test_boost_interval=7". It is + usually wise for this value to be relatively prime to + the value selected for "stutter". + +test_boost_duration + The number of seconds to do RCU priority-inversion testing + within any given "test_boost_interval". Defaults to + "test_boost_duration=4". + test_no_idle_hz Whether or not to test the ability of RCU to operate in a kernel that disables the scheduling-clock interrupt to idle CPUs. Boolean parameter, "1" to test, "0" otherwise. Defaults to omitting this test. -torture_type The type of RCU to test: "rcu" for the rcu_read_lock() API, - "rcu_sync" for rcu_read_lock() with synchronous reclamation, - "rcu_bh" for the rcu_read_lock_bh() API, "rcu_bh_sync" for - rcu_read_lock_bh() with synchronous reclamation, "srcu" for - the "srcu_read_lock()" API, "sched" for the use of - preempt_disable() together with synchronize_sched(), - and "sched_expedited" for the use of preempt_disable() - with synchronize_sched_expedited(). +torture_type The type of RCU to test, with string values as follows: + + "rcu": rcu_read_lock(), rcu_read_unlock() and call_rcu(). + + "rcu_sync": rcu_read_lock(), rcu_read_unlock(), and + synchronize_rcu(). + + "rcu_expedited": rcu_read_lock(), rcu_read_unlock(), and + synchronize_rcu_expedited(). + + "rcu_bh": rcu_read_lock_bh(), rcu_read_unlock_bh(), and + call_rcu_bh(). + + "rcu_bh_sync": rcu_read_lock_bh(), rcu_read_unlock_bh(), + and synchronize_rcu_bh(). + + "rcu_bh_expedited": rcu_read_lock_bh(), rcu_read_unlock_bh(), + and synchronize_rcu_bh_expedited(). + + "srcu": srcu_read_lock(), srcu_read_unlock() and + synchronize_srcu(). + + "srcu_expedited": srcu_read_lock(), srcu_read_unlock() and + synchronize_srcu_expedited(). + + "sched": preempt_disable(), preempt_enable(), and + call_rcu_sched(). + + "sched_sync": preempt_disable(), preempt_enable(), and + synchronize_sched(). + + "sched_expedited": preempt_disable(), preempt_enable(), and + synchronize_sched_expedited(). + + Defaults to "rcu". verbose Enable debug printk()s. Default is disabled. @@ -100,12 +149,12 @@ OUTPUT The statistics output is as follows: - rcu-torture: --- Start of test: nreaders=16 stat_interval=0 verbose=0 - rcu-torture: rtc: 0000000000000000 ver: 1916 tfle: 0 rta: 1916 rtaf: 0 rtf: 1915 - rcu-torture: Reader Pipe: 1466408 9747 0 0 0 0 0 0 0 0 0 - rcu-torture: Reader Batch: 1464477 11678 0 0 0 0 0 0 0 0 - rcu-torture: Free-Block Circulation: 1915 1915 1915 1915 1915 1915 1915 1915 1915 1915 0 - rcu-torture: --- End of test + rcu-torture:--- Start of test: nreaders=16 nfakewriters=4 stat_interval=30 verbose=0 test_no_idle_hz=1 shuffle_interval=3 stutter=5 irqreader=1 fqs_duration=0 fqs_holdoff=0 fqs_stutter=3 test_boost=1/0 test_boost_interval=7 test_boost_duration=4 + rcu-torture: rtc: (null) ver: 155441 tfle: 0 rta: 155441 rtaf: 8884 rtf: 155440 rtmbe: 0 rtbke: 0 rtbre: 0 rtbf: 0 rtb: 0 nt: 3055767 + rcu-torture: Reader Pipe: 727860534 34213 0 0 0 0 0 0 0 0 0 + rcu-torture: Reader Batch: 727877838 17003 0 0 0 0 0 0 0 0 0 + rcu-torture: Free-Block Circulation: 155440 155440 155440 155440 155440 155440 155440 155440 155440 155440 0 + rcu-torture:--- End of test: SUCCESS: nreaders=16 nfakewriters=4 stat_interval=30 verbose=0 test_no_idle_hz=1 shuffle_interval=3 stutter=5 irqreader=1 fqs_duration=0 fqs_holdoff=0 fqs_stutter=3 test_boost=1/0 test_boost_interval=7 test_boost_duration=4 The command "dmesg | grep torture:" will extract this information on most systems. On more esoteric configurations, it may be necessary to @@ -113,26 +162,55 @@ use other commands to access the output of the printk()s used by the RCU torture test. The printk()s use KERN_ALERT, so they should be evident. ;-) +The first and last lines show the rcutorture module parameters, and the +last line shows either "SUCCESS" or "FAILURE", based on rcutorture's +automatic determination as to whether RCU operated correctly. + The entries are as follows: o "rtc": The hexadecimal address of the structure currently visible to readers. -o "ver": The number of times since boot that the rcutw writer task +o "ver": The number of times since boot that the RCU writer task has changed the structure visible to readers. o "tfle": If non-zero, indicates that the "torture freelist" - containing structure to be placed into the "rtc" area is empty. + containing structures to be placed into the "rtc" area is empty. This condition is important, since it can fool you into thinking that RCU is working when it is not. :-/ o "rta": Number of structures allocated from the torture freelist. o "rtaf": Number of allocations from the torture freelist that have - failed due to the list being empty. + failed due to the list being empty. It is not unusual for this + to be non-zero, but it is bad for it to be a large fraction of + the value indicated by "rta". o "rtf": Number of frees into the torture freelist. +o "rtmbe": A non-zero value indicates that rcutorture believes that + rcu_assign_pointer() and rcu_dereference() are not working + correctly. This value should be zero. + +o "rtbke": rcutorture was unable to create the real-time kthreads + used to force RCU priority inversion. This value should be zero. + +o "rtbre": Although rcutorture successfully created the kthreads + used to force RCU priority inversion, it was unable to set them + to the real-time priority level of 1. This value should be zero. + +o "rtbf": The number of times that RCU priority boosting failed + to resolve RCU priority inversion. + +o "rtb": The number of times that rcutorture attempted to force + an RCU priority inversion condition. If you are testing RCU + priority boosting via the "test_boost" module parameter, this + value should be non-zero. + +o "nt": The number of times rcutorture ran RCU read-side code from + within a timer handler. This value should be non-zero only + if you specified the "irqreader" module parameter. + o "Reader Pipe": Histogram of "ages" of structures seen by readers. If any entries past the first two are non-zero, RCU is broken. And rcutorture prints the error flag string "!!!" to make sure @@ -162,26 +240,15 @@ o "Free-Block Circulation": Shows the number of torture structures somehow gets incremented farther than it should. Different implementations of RCU can provide implementation-specific -additional information. For example, SRCU provides the following: +additional information. For example, SRCU provides the following +additional line: - srcu-torture: rtc: f8cf46a8 ver: 355 tfle: 0 rta: 356 rtaf: 0 rtf: 346 rtmbe: 0 - srcu-torture: Reader Pipe: 559738 939 0 0 0 0 0 0 0 0 0 - srcu-torture: Reader Batch: 560434 243 0 0 0 0 0 0 0 0 - srcu-torture: Free-Block Circulation: 355 354 353 352 351 350 349 348 347 346 0 srcu-torture: per-CPU(idx=1): 0(0,1) 1(0,1) 2(0,0) 3(0,1) -The first four lines are similar to those for RCU. The last line shows -the per-CPU counter state. The numbers in parentheses are the values -of the "old" and "current" counters for the corresponding CPU. The -"idx" value maps the "old" and "current" values to the underlying array, -and is useful for debugging. - -Similarly, sched_expedited RCU provides the following: - - sched_expedited-torture: rtc: d0000000016c1880 ver: 1090796 tfle: 0 rta: 1090796 rtaf: 0 rtf: 1090787 rtmbe: 0 nt: 27713319 - sched_expedited-torture: Reader Pipe: 12660320201 95875 0 0 0 0 0 0 0 0 0 - sched_expedited-torture: Reader Batch: 12660424885 0 0 0 0 0 0 0 0 0 0 - sched_expedited-torture: Free-Block Circulation: 1090795 1090795 1090794 1090793 1090792 1090791 1090790 1090789 1090788 1090787 0 +This line shows the per-CPU counter state. The numbers in parentheses are +the values of the "old" and "current" counters for the corresponding CPU. +The "idx" value maps the "old" and "current" values to the underlying +array, and is useful for debugging. USAGE diff --git a/Documentation/RCU/trace.txt b/Documentation/RCU/trace.txt index 8173cec473aa0099a185d694bad1b1b6ee48743d..aaf65f6c6cd7845e7cf671366671b713bcd8fe16 100644 --- a/Documentation/RCU/trace.txt +++ b/Documentation/RCU/trace.txt @@ -33,23 +33,23 @@ rcu/rcuboost: The output of "cat rcu/rcudata" looks as follows: rcu_sched: - 0 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=545/1/0 df=50 of=0 ri=0 ql=163 qs=NRW. kt=0/W/0 ktl=ebc3 b=10 ci=153737 co=0 ca=0 - 1 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=967/1/0 df=58 of=0 ri=0 ql=634 qs=NRW. kt=0/W/1 ktl=58c b=10 ci=191037 co=0 ca=0 - 2 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=1081/1/0 df=175 of=0 ri=0 ql=74 qs=N.W. kt=0/W/2 ktl=da94 b=10 ci=75991 co=0 ca=0 - 3 c=20942 g=20943 pq=1 pqc=20942 qp=1 dt=1846/0/0 df=404 of=0 ri=0 ql=0 qs=.... kt=0/W/3 ktl=d1cd b=10 ci=72261 co=0 ca=0 - 4 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=369/1/0 df=83 of=0 ri=0 ql=48 qs=N.W. kt=0/W/4 ktl=e0e7 b=10 ci=128365 co=0 ca=0 - 5 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=381/1/0 df=64 of=0 ri=0 ql=169 qs=NRW. kt=0/W/5 ktl=fb2f b=10 ci=164360 co=0 ca=0 - 6 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=1037/1/0 df=183 of=0 ri=0 ql=62 qs=N.W. kt=0/W/6 ktl=d2ad b=10 ci=65663 co=0 ca=0 - 7 c=20897 g=20897 pq=1 pqc=20896 qp=0 dt=1572/0/0 df=382 of=0 ri=0 ql=0 qs=.... kt=0/W/7 ktl=cf15 b=10 ci=75006 co=0 ca=0 + 0 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=545/1/0 df=50 of=0 ri=0 ql=163 qs=NRW. kt=0/W/0 ktl=ebc3 b=10 ci=153737 co=0 ca=0 + 1 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=967/1/0 df=58 of=0 ri=0 ql=634 qs=NRW. kt=0/W/1 ktl=58c b=10 ci=191037 co=0 ca=0 + 2 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=1081/1/0 df=175 of=0 ri=0 ql=74 qs=N.W. kt=0/W/2 ktl=da94 b=10 ci=75991 co=0 ca=0 + 3 c=20942 g=20943 pq=1 pgp=20942 qp=1 dt=1846/0/0 df=404 of=0 ri=0 ql=0 qs=.... kt=0/W/3 ktl=d1cd b=10 ci=72261 co=0 ca=0 + 4 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=369/1/0 df=83 of=0 ri=0 ql=48 qs=N.W. kt=0/W/4 ktl=e0e7 b=10 ci=128365 co=0 ca=0 + 5 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=381/1/0 df=64 of=0 ri=0 ql=169 qs=NRW. kt=0/W/5 ktl=fb2f b=10 ci=164360 co=0 ca=0 + 6 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=1037/1/0 df=183 of=0 ri=0 ql=62 qs=N.W. kt=0/W/6 ktl=d2ad b=10 ci=65663 co=0 ca=0 + 7 c=20897 g=20897 pq=1 pgp=20896 qp=0 dt=1572/0/0 df=382 of=0 ri=0 ql=0 qs=.... kt=0/W/7 ktl=cf15 b=10 ci=75006 co=0 ca=0 rcu_bh: - 0 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=545/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/0 ktl=ebc3 b=10 ci=0 co=0 ca=0 - 1 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=967/1/0 df=3 of=0 ri=1 ql=0 qs=.... kt=0/W/1 ktl=58c b=10 ci=151 co=0 ca=0 - 2 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=1081/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/2 ktl=da94 b=10 ci=0 co=0 ca=0 - 3 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=1846/0/0 df=8 of=0 ri=1 ql=0 qs=.... kt=0/W/3 ktl=d1cd b=10 ci=0 co=0 ca=0 - 4 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=369/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/4 ktl=e0e7 b=10 ci=0 co=0 ca=0 - 5 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=381/1/0 df=4 of=0 ri=1 ql=0 qs=.... kt=0/W/5 ktl=fb2f b=10 ci=0 co=0 ca=0 - 6 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=1037/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/6 ktl=d2ad b=10 ci=0 co=0 ca=0 - 7 c=1474 g=1474 pq=1 pqc=1473 qp=0 dt=1572/0/0 df=8 of=0 ri=1 ql=0 qs=.... kt=0/W/7 ktl=cf15 b=10 ci=0 co=0 ca=0 + 0 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=545/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/0 ktl=ebc3 b=10 ci=0 co=0 ca=0 + 1 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=967/1/0 df=3 of=0 ri=1 ql=0 qs=.... kt=0/W/1 ktl=58c b=10 ci=151 co=0 ca=0 + 2 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=1081/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/2 ktl=da94 b=10 ci=0 co=0 ca=0 + 3 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=1846/0/0 df=8 of=0 ri=1 ql=0 qs=.... kt=0/W/3 ktl=d1cd b=10 ci=0 co=0 ca=0 + 4 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=369/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/4 ktl=e0e7 b=10 ci=0 co=0 ca=0 + 5 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=381/1/0 df=4 of=0 ri=1 ql=0 qs=.... kt=0/W/5 ktl=fb2f b=10 ci=0 co=0 ca=0 + 6 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=1037/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/6 ktl=d2ad b=10 ci=0 co=0 ca=0 + 7 c=1474 g=1474 pq=1 pgp=1473 qp=0 dt=1572/0/0 df=8 of=0 ri=1 ql=0 qs=.... kt=0/W/7 ktl=cf15 b=10 ci=0 co=0 ca=0 The first section lists the rcu_data structures for rcu_sched, the second for rcu_bh. Note that CONFIG_TREE_PREEMPT_RCU kernels will have an @@ -84,7 +84,7 @@ o "pq" indicates that this CPU has passed through a quiescent state CPU has not yet reported that fact, (2) some other CPU has not yet reported for this grace period, or (3) both. -o "pqc" indicates which grace period the last-observed quiescent +o "pgp" indicates which grace period the last-observed quiescent state for this CPU corresponds to. This is important for handling the race between CPU 0 reporting an extended dynticks-idle quiescent state for CPU 1 and CPU 1 suddenly waking up and @@ -184,10 +184,14 @@ o "kt" is the per-CPU kernel-thread state. The digit preceding The number after the final slash is the CPU that the kthread is actually running on. + This field is displayed only for CONFIG_RCU_BOOST kernels. + o "ktl" is the low-order 16 bits (in hexadecimal) of the count of the number of times that this CPU's per-CPU kthread has gone through its loop servicing invoke_rcu_cpu_kthread() requests. + This field is displayed only for CONFIG_RCU_BOOST kernels. + o "b" is the batch limit for this CPU. If more than this number of RCU callbacks is ready to invoke, then the remainder will be deferred. diff --git a/Documentation/blackfin/bfin-gpio-notes.txt b/Documentation/blackfin/bfin-gpio-notes.txt index f731c1e5647525293fda207661cbfa741caf6d74..d36b01f778b9e450a07a7b49dffab29553faec63 100644 --- a/Documentation/blackfin/bfin-gpio-notes.txt +++ b/Documentation/blackfin/bfin-gpio-notes.txt @@ -1,5 +1,5 @@ /* - * File: Documentation/blackfin/bfin-gpio-note.txt + * File: Documentation/blackfin/bfin-gpio-notes.txt * Based on: * Author: * diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt index c6d84cfd2f56a55d2892e8e6afbea2383274ce95..e418dc0a7086631488963786f9ddb0f3d897b147 100644 --- a/Documentation/block/biodoc.txt +++ b/Documentation/block/biodoc.txt @@ -186,7 +186,7 @@ a virtual address mapping (unlike the earlier scheme of virtual address do not have a corresponding kernel virtual address space mapping) and low-memory pages. -Note: Please refer to Documentation/PCI/PCI-DMA-mapping.txt for a discussion +Note: Please refer to Documentation/DMA-API-HOWTO.txt for a discussion on PCI high mem DMA aspects and mapping of scatter gather lists, and support for 64 bit PCI. diff --git a/Documentation/bus-virt-phys-mapping.txt b/Documentation/bus-virt-phys-mapping.txt index 1b5aa10df84564ee5f3278abbe5b836a521839d2..2bc55ff3b4d1e2db24906a41ba71e7da8b900688 100644 --- a/Documentation/bus-virt-phys-mapping.txt +++ b/Documentation/bus-virt-phys-mapping.txt @@ -1,6 +1,6 @@ [ NOTE: The virt_to_bus() and bus_to_virt() functions have been superseded by the functionality provided by the PCI DMA interface - (see Documentation/PCI/PCI-DMA-mapping.txt). They continue + (see Documentation/DMA-API-HOWTO.txt). They continue to be documented below for historical purposes, but new code must not use them. --davidm 00/12/12 ] diff --git a/Documentation/cdrom/packet-writing.txt b/Documentation/cdrom/packet-writing.txt index 13c251d5add6cce112f94e6050ba8f3bfe63670e..2834170d821e79d4d4f9dd116ea2188fd09352e2 100644 --- a/Documentation/cdrom/packet-writing.txt +++ b/Documentation/cdrom/packet-writing.txt @@ -109,7 +109,7 @@ this interface. (see http://tom.ist-im-web.de/download/pktcdvd ) For a description of the sysfs interface look into the file: - Documentation/ABI/testing/sysfs-block-pktcdvd + Documentation/ABI/testing/sysfs-class-pktcdvd Using the pktcdvd debugfs interface diff --git a/Documentation/cpu-freq/governors.txt b/Documentation/cpu-freq/governors.txt index e74d0a2eb1cf4d9921b0720039c6696e42fc3062..d221781dabaa84f49977d985fe617f74dfdb090a 100644 --- a/Documentation/cpu-freq/governors.txt +++ b/Documentation/cpu-freq/governors.txt @@ -132,7 +132,7 @@ The sampling rate is limited by the HW transition latency: transition_latency * 100 Or by kernel restrictions: If CONFIG_NO_HZ is set, the limit is 10ms fixed. -If CONFIG_NO_HZ is not set or no_hz=off boot parameter is used, the +If CONFIG_NO_HZ is not set or nohz=off boot parameter is used, the limits depend on the CONFIG_HZ option: HZ=1000: min=20000us (20ms) HZ=250: min=80000us (80ms) diff --git a/Documentation/development-process/4.Coding b/Documentation/development-process/4.Coding index 83f5f5b365a3fdb5a79e0cf9106697d937994cf4..e3cb6a56653a69fa3b223ccc7ba565cec5802f8d 100644 --- a/Documentation/development-process/4.Coding +++ b/Documentation/development-process/4.Coding @@ -278,7 +278,7 @@ enabled, a configurable percentage of memory allocations will be made to fail; these failures can be restricted to a specific range of code. Running with fault injection enabled allows the programmer to see how the code responds when things go badly. See -Documentation/fault-injection/fault-injection.text for more information on +Documentation/fault-injection/fault-injection.txt for more information on how to use this facility. Other kinds of errors can be found with the "sparse" static analysis tool. diff --git a/Documentation/devicetree/bindings/arm/calxeda.txt b/Documentation/devicetree/bindings/arm/calxeda.txt new file mode 100644 index 0000000000000000000000000000000000000000..4755caaccba645bf23766df43cd8ed431b899475 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/calxeda.txt @@ -0,0 +1,8 @@ +Calxeda Highbank Platforms Device Tree Bindings +----------------------------------------------- + +Boards with Calxeda Cortex-A9 based Highbank SOC shall have the following +properties. + +Required root node properties: + - compatible = "calxeda,highbank"; diff --git a/Documentation/devicetree/bindings/arm/fsl.txt b/Documentation/devicetree/bindings/arm/fsl.txt new file mode 100644 index 0000000000000000000000000000000000000000..c9848ad0e2e3c65967d5c047284a399987b32f33 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/fsl.txt @@ -0,0 +1,26 @@ +Freescale i.MX Platforms Device Tree Bindings +----------------------------------------------- + +i.MX51 Babbage Board +Required root node properties: + - compatible = "fsl,imx51-babbage", "fsl,imx51"; + +i.MX53 Automotive Reference Design Board +Required root node properties: + - compatible = "fsl,imx53-ard", "fsl,imx53"; + +i.MX53 Evaluation Kit +Required root node properties: + - compatible = "fsl,imx53-evk", "fsl,imx53"; + +i.MX53 Quick Start Board +Required root node properties: + - compatible = "fsl,imx53-qsb", "fsl,imx53"; + +i.MX53 Smart Mobile Reference Design Board +Required root node properties: + - compatible = "fsl,imx53-smd", "fsl,imx53"; + +i.MX6 Quad SABRE Automotive Board +Required root node properties: + - compatible = "fsl,imx6q-sabreauto", "fsl,imx6q"; diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt new file mode 100644 index 0000000000000000000000000000000000000000..52916b4aa1fe9b70201b2fd44f3b91893c76600b --- /dev/null +++ b/Documentation/devicetree/bindings/arm/gic.txt @@ -0,0 +1,55 @@ +* ARM Generic Interrupt Controller + +ARM SMP cores are often associated with a GIC, providing per processor +interrupts (PPI), shared processor interrupts (SPI) and software +generated interrupts (SGI). + +Primary GIC is attached directly to the CPU and typically has PPIs and SGIs. +Secondary GICs are cascaded into the upward interrupt controller and do not +have PPIs or SGIs. + +Main node required properties: + +- compatible : should be one of: + "arm,cortex-a9-gic" + "arm,arm11mp-gic" +- interrupt-controller : Identifies the node as an interrupt controller +- #interrupt-cells : Specifies the number of cells needed to encode an + interrupt source. The type shall be a and the value shall be 3. + + The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI + interrupts. + + The 2nd cell contains the interrupt number for the interrupt type. + SPI interrupts are in the range [0-987]. PPI interrupts are in the + range [0-15]. + + The 3rd cell is the flags, encoded as follows: + bits[3:0] trigger type and level flags. + 1 = low-to-high edge triggered + 2 = high-to-low edge triggered + 4 = active high level-sensitive + 8 = active low level-sensitive + bits[15:8] PPI interrupt cpu mask. Each bit corresponds to each of + the 8 possible cpus attached to the GIC. A bit set to '1' indicated + the interrupt is wired to that CPU. Only valid for PPI interrupts. + +- reg : Specifies base physical address(s) and size of the GIC registers. The + first region is the GIC distributor register base and size. The 2nd region is + the GIC cpu interface register base and size. + +Optional +- interrupts : Interrupt source of the parent interrupt controller. Only + present on secondary GICs. + +Example: + + intc: interrupt-controller@fff11000 { + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <1>; + interrupt-controller; + reg = <0xfff11000 0x1000>, + <0xfff10100 0x100>; + }; + diff --git a/Documentation/devicetree/bindings/arm/l2cc.txt b/Documentation/devicetree/bindings/arm/l2cc.txt new file mode 100644 index 0000000000000000000000000000000000000000..7ca52161e7ab99df27334b1445d015365a053f0d --- /dev/null +++ b/Documentation/devicetree/bindings/arm/l2cc.txt @@ -0,0 +1,44 @@ +* ARM L2 Cache Controller + +ARM cores often have a separate level 2 cache controller. There are various +implementations of the L2 cache controller with compatible programming models. +The ARM L2 cache representation in the device tree should be done as follows: + +Required properties: + +- compatible : should be one of: + "arm,pl310-cache" + "arm,l220-cache" + "arm,l210-cache" +- cache-unified : Specifies the cache is a unified cache. +- cache-level : Should be set to 2 for a level 2 cache. +- reg : Physical base address and size of cache controller's memory mapped + registers. + +Optional properties: + +- arm,data-latency : Cycles of latency for Data RAM accesses. Specifies 3 cells of + read, write and setup latencies. Minimum valid values are 1. Controllers + without setup latency control should use a value of 0. +- arm,tag-latency : Cycles of latency for Tag RAM accesses. Specifies 3 cells of + read, write and setup latencies. Controllers without setup latency control + should use 0. Controllers without separate read and write Tag RAM latency + values should only use the first cell. +- arm,dirty-latency : Cycles of latency for Dirty RAMs. This is a single cell. +- arm,filter-ranges : Starting address and length of window to + filter. Addresses in the filter window are directed to the M1 port. Other + addresses will go to the M0 port. +- interrupts : 1 combined interrupt. + +Example: + +L2: cache-controller { + compatible = "arm,pl310-cache"; + reg = <0xfff12000 0x1000>; + arm,data-latency = <1 1 1>; + arm,tag-latency = <2 2 2>; + arm,filter-latency = <0x80000000 0x8000000>; + cache-unified; + cache-level = <2>; + interrupts = <45>; +}; diff --git a/Documentation/devicetree/bindings/arm/omap/dsp.txt b/Documentation/devicetree/bindings/arm/omap/dsp.txt new file mode 100644 index 0000000000000000000000000000000000000000..d3830a32ce08596a32c3638e05ddd15877f7925d --- /dev/null +++ b/Documentation/devicetree/bindings/arm/omap/dsp.txt @@ -0,0 +1,14 @@ +* TI - DSP (Digital Signal Processor) + +TI DSP included in OMAP SoC + +Required properties: +- compatible : Should be "ti,omap3-c64" for OMAP3 & 4 +- ti,hwmods: "dsp" + +Examples: + +dsp { + compatible = "ti,omap3-c64"; + ti,hwmods = "dsp"; +}; diff --git a/Documentation/devicetree/bindings/arm/omap/iva.txt b/Documentation/devicetree/bindings/arm/omap/iva.txt new file mode 100644 index 0000000000000000000000000000000000000000..6d629517135880cc5519280acc84768b076cbaa9 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/omap/iva.txt @@ -0,0 +1,19 @@ +* TI - IVA (Imaging and Video Accelerator) subsystem + +The IVA contain various audio, video or imaging HW accelerator +depending of the version. + +Required properties: +- compatible : Should be: + - "ti,ivahd" for OMAP4 + - "ti,iva2.2" for OMAP3 + - "ti,iva2.1" for OMAP2430 + - "ti,iva1" for OMAP2420 +- ti,hwmods: "iva" + +Examples: + +iva { + compatible = "ti,ivahd", "ti,iva"; + ti,hwmods = "iva"; +}; diff --git a/Documentation/devicetree/bindings/arm/omap/l3-noc.txt b/Documentation/devicetree/bindings/arm/omap/l3-noc.txt new file mode 100644 index 0000000000000000000000000000000000000000..6888a5efc860b7ad4c64274aeab6bb77346e4ef9 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/omap/l3-noc.txt @@ -0,0 +1,19 @@ +* TI - L3 Network On Chip (NoC) + +This version is an implementation of the generic NoC IP +provided by Arteris. + +Required properties: +- compatible : Should be "ti,omap3-l3-smx" for OMAP3 family + Should be "ti,omap4-l3-noc" for OMAP4 family +- ti,hwmods: "l3_main_1", ... One hwmod for each noc domain. + +Examples: + +ocp { + compatible = "ti,omap4-l3-noc", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + ti,hwmods = "l3_main_1", "l3_main_2", "l3_main_3"; +}; diff --git a/Documentation/devicetree/bindings/arm/omap/mpu.txt b/Documentation/devicetree/bindings/arm/omap/mpu.txt new file mode 100644 index 0000000000000000000000000000000000000000..1a5a42ce21bb0ac7480b07ca9aced96914c33910 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/omap/mpu.txt @@ -0,0 +1,27 @@ +* TI - MPU (Main Processor Unit) subsystem + +The MPU subsystem contain one or several ARM cores +depending of the version. +The MPU contain CPUs, GIC, L2 cache and a local PRCM. + +Required properties: +- compatible : Should be "ti,omap3-mpu" for OMAP3 + Should be "ti,omap4-mpu" for OMAP4 +- ti,hwmods: "mpu" + +Examples: + +- For an OMAP4 SMP system: + +mpu { + compatible = "ti,omap4-mpu"; + ti,hwmods = "mpu"; +}; + + +- For an OMAP3 monocore system: + +mpu { + compatible = "ti,omap3-mpu"; + ti,hwmods = "mpu"; +}; diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt new file mode 100644 index 0000000000000000000000000000000000000000..dbdab40ed3a62471879a1a6fb7b0d53c545cc8f9 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/omap/omap.txt @@ -0,0 +1,43 @@ +* Texas Instruments OMAP + +OMAP is currently using a static file per SoC family to describe the +IPs present in the SoC. +On top of that an omap_device is created to extend the platform_device +capabilities and to allow binding with one or several hwmods. +The hwmods will contain all the information to build the device: +adresse range, irq lines, dma lines, interconnect, PRCM register, +clock domain, input clocks. +For the moment just point to the existing hwmod, the next step will be +to move data from hwmod to device-tree representation. + + +Required properties: +- compatible: Every devices present in OMAP SoC should be in the + form: "ti,XXX" +- ti,hwmods: list of hwmod names (ascii strings), that comes from the OMAP + HW documentation, attached to a device. Must contain at least + one hwmod. + +Optional properties: +- ti,no_idle_on_suspend: When present, it prevents the PM to idle the module + during suspend. + + +Example: + +spinlock@1 { + compatible = "ti,omap4-spinlock"; + ti,hwmods = "spinlock"; +}; + + +Boards: + +- OMAP3 BeagleBoard : Low cost community board + compatible = "ti,omap3-beagle", "ti,omap3" + +- OMAP4 SDP : Software Developement Board + compatible = "ti,omap4-sdp", "ti,omap4430" + +- OMAP4 PandaBoard : Low cost community board + compatible = "ti,omap4-panda", "ti,omap4430" diff --git a/Documentation/devicetree/bindings/arm/picoxcell.txt b/Documentation/devicetree/bindings/arm/picoxcell.txt new file mode 100644 index 0000000000000000000000000000000000000000..e75c0ef51e69fc05152236b7d3faa7038217fc11 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/picoxcell.txt @@ -0,0 +1,24 @@ +Picochip picoXcell device tree bindings. +======================================== + +Required root node properties: + - compatible: + - "picochip,pc7302-pc3x3" : PC7302 development board with PC3X3 device. + - "picochip,pc7302-pc3x2" : PC7302 development board with PC3X2 device. + - "picochip,pc3x3" : picoXcell PC3X3 device based board. + - "picochip,pc3x2" : picoXcell PC3X2 device based board. + +Timers required properties: + - compatible = "picochip,pc3x2-timer" + - interrupts : The single IRQ line for the timer. + - clock-freq : The frequency in HZ of the timer. + - reg : The register bank for the timer. + +Note: two timers are required - one for the scheduler clock and one for the +event tick/NOHZ. + +VIC required properties: + - compatible = "arm,pl192-vic". + - interrupt-controller. + - reg : The register bank for the device. + - #interrupt-cells : Must be 1. diff --git a/Documentation/devicetree/bindings/arm/primecell.txt b/Documentation/devicetree/bindings/arm/primecell.txt index 1d5d7a870ec72db9668eaedd9e983fcc220d2017..951ca46789d4130dc8573913943ca429a7812241 100644 --- a/Documentation/devicetree/bindings/arm/primecell.txt +++ b/Documentation/devicetree/bindings/arm/primecell.txt @@ -6,7 +6,9 @@ driver matching. Required properties: -- compatible : should be a specific value for peripheral and "arm,primecell" +- compatible : should be a specific name for the peripheral and + "arm,primecell". The specific name will match the ARM + engineering name for the logic block in the form: "arm,pl???" Optional properties: diff --git a/Documentation/devicetree/bindings/crypto/picochip-spacc.txt b/Documentation/devicetree/bindings/crypto/picochip-spacc.txt new file mode 100644 index 0000000000000000000000000000000000000000..d8609ece1f4c4eea56bdf3c475fa486554f850d1 --- /dev/null +++ b/Documentation/devicetree/bindings/crypto/picochip-spacc.txt @@ -0,0 +1,23 @@ +Picochip picoXcell SPAcc (Security Protocol Accelerator) bindings + +Picochip picoXcell devices contain crypto offload engines that may be used for +IPSEC and femtocell layer 2 ciphering. + +Required properties: + - compatible : "picochip,spacc-ipsec" for the IPSEC offload engine + "picochip,spacc-l2" for the femtocell layer 2 ciphering engine. + - reg : Offset and length of the register set for this device + - interrupt-parent : The interrupt controller that controls the SPAcc + interrupt. + - interrupts : The interrupt line from the SPAcc. + - ref-clock : The input clock that drives the SPAcc. + +Example SPAcc node: + +spacc@10000 { + compatible = "picochip,spacc-ipsec"; + reg = <0x100000 0x10000>; + interrupt-parent = <&vic0>; + interrupts = <24>; + ref-clock = <&ipsec_clk>, "ref"; +}; diff --git a/Documentation/devicetree/bindings/gpio/led.txt b/Documentation/devicetree/bindings/gpio/led.txt index 064db928c3c12cc3d6141664e57d25e7050520ed..141087cf3107733b8bb4e2c33a8fcd5dbba8076c 100644 --- a/Documentation/devicetree/bindings/gpio/led.txt +++ b/Documentation/devicetree/bindings/gpio/led.txt @@ -8,7 +8,7 @@ node's name represents the name of the corresponding LED. LED sub-node properties: - gpios : Should specify the LED's GPIO, see "Specifying GPIO information - for devices" in Documentation/powerpc/booting-without-of.txt. Active + for devices" in Documentation/devicetree/booting-without-of.txt. Active low LEDs should be indicated using flags in the GPIO specifier. - label : (optional) The label for this LED. If omitted, the label is taken from the node name (excluding the unit address). diff --git a/Documentation/devicetree/bindings/gpio/pl061-gpio.txt b/Documentation/devicetree/bindings/gpio/pl061-gpio.txt new file mode 100644 index 0000000000000000000000000000000000000000..a2c416bcbccce950741ce69db3d5817fac26fa6d --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/pl061-gpio.txt @@ -0,0 +1,10 @@ +ARM PL061 GPIO controller + +Required properties: +- compatible : "arm,pl061", "arm,primecell" +- #gpio-cells : Should be two. The first cell is the pin number and the + second cell is used to specify optional parameters: + - bit 0 specifies polarity (0 for normal, 1 for inverted) +- gpio-controller : Marks the device node as a GPIO controller. +- interrupts : Interrupt mapping for GPIO IRQ. + diff --git a/Documentation/devicetree/bindings/i2c/fsl-imx-i2c.txt b/Documentation/devicetree/bindings/i2c/fsl-imx-i2c.txt new file mode 100644 index 0000000000000000000000000000000000000000..f3cf43b66f7e0e45da4402e6181a8487e0f26329 --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/fsl-imx-i2c.txt @@ -0,0 +1,25 @@ +* Freescale Inter IC (I2C) and High Speed Inter IC (HS-I2C) for i.MX + +Required properties: +- compatible : Should be "fsl,-i2c" +- reg : Should contain I2C/HS-I2C registers location and length +- interrupts : Should contain I2C/HS-I2C interrupt + +Optional properties: +- clock-frequency : Constains desired I2C/HS-I2C bus clock frequency in Hz. + The absence of the propoerty indicates the default frequency 100 kHz. + +Examples: + +i2c@83fc4000 { /* I2C2 on i.MX51 */ + compatible = "fsl,imx51-i2c", "fsl,imx1-i2c"; + reg = <0x83fc4000 0x4000>; + interrupts = <63>; +}; + +i2c@70038000 { /* HS-I2C on i.MX51 */ + compatible = "fsl,imx51-i2c", "fsl,imx1-i2c"; + reg = <0x70038000 0x4000>; + interrupts = <64>; + clock-frequency = <400000>; +}; diff --git a/Documentation/devicetree/bindings/i2c/samsung-i2c.txt b/Documentation/devicetree/bindings/i2c/samsung-i2c.txt new file mode 100644 index 0000000000000000000000000000000000000000..38832c712919aa25fe4e2ba2d2368708e32953f6 --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/samsung-i2c.txt @@ -0,0 +1,39 @@ +* Samsung's I2C controller + +The Samsung's I2C controller is used to interface with I2C devices. + +Required properties: + - compatible: value should be either of the following. + (a) "samsung, s3c2410-i2c", for i2c compatible with s3c2410 i2c. + (b) "samsung, s3c2440-i2c", for i2c compatible with s3c2440 i2c. + - reg: physical base address of the controller and length of memory mapped + region. + - interrupts: interrupt number to the cpu. + - samsung,i2c-sda-delay: Delay (in ns) applied to data line (SDA) edges. + - gpios: The order of the gpios should be the following: . + The gpio specifier depends on the gpio controller. + +Optional properties: + - samsung,i2c-slave-addr: Slave address in multi-master enviroment. If not + specified, default value is 0. + - samsung,i2c-max-bus-freq: Desired frequency in Hz of the bus. If not + specified, the default value in Hz is 100000. + +Example: + + i2c@13870000 { + compatible = "samsung,s3c2440-i2c"; + reg = <0x13870000 0x100>; + interrupts = <345>; + samsung,i2c-sda-delay = <100>; + samsung,i2c-max-bus-freq = <100000>; + gpios = <&gpd1 2 0 /* SDA */ + &gpd1 3 0 /* SCL */>; + #address-cells = <1>; + #size-cells = <0>; + + wm8994@1a { + compatible = "wlf,wm8994"; + reg = <0x1a>; + }; + }; diff --git a/Documentation/devicetree/bindings/mmc/nvidia-sdhci.txt b/Documentation/devicetree/bindings/mmc/nvidia-sdhci.txt new file mode 100644 index 0000000000000000000000000000000000000000..7e51154679a6f17d47ce198b77dd2eeade185dc6 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/nvidia-sdhci.txt @@ -0,0 +1,27 @@ +* NVIDIA Tegra Secure Digital Host Controller + +This controller on Tegra family SoCs provides an interface for MMC, SD, +and SDIO types of memory cards. + +Required properties: +- compatible : Should be "nvidia,-sdhci" +- reg : Should contain SD/MMC registers location and length +- interrupts : Should contain SD/MMC interrupt + +Optional properties: +- cd-gpios : Specify GPIOs for card detection +- wp-gpios : Specify GPIOs for write protection +- power-gpios : Specify GPIOs for power control +- support-8bit : Boolean, indicates if 8-bit mode should be used. + +Example: + +sdhci@c8000200 { + compatible = "nvidia,tegra20-sdhci"; + reg = <0xc8000200 0x200>; + interrupts = <47>; + cd-gpios = <&gpio 69 0>; /* gpio PI5 */ + wp-gpios = <&gpio 57 0>; /* gpio PH1 */ + power-gpios = <&gpio 155 0>; /* gpio PT3 */ + support-8bit; +}; diff --git a/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt b/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt index 1a729f089866259ef82d0db5893ff7a8c54d5ccf..1ad80d5865a9848c10869814b0cc32118d093fc9 100644 --- a/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt +++ b/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt @@ -1,61 +1,24 @@ -CAN Device Tree Bindings ------------------------- -2011 Freescale Semiconductor, Inc. +Flexcan CAN contoller on Freescale's ARM and PowerPC system-on-a-chip (SOC). -fsl,flexcan-v1.0 nodes ------------------------ -In addition to the required compatible-, reg- and interrupt-properties, you can -also specify which clock source shall be used for the controller. +Required properties: -CPI Clock- Can Protocol Interface Clock - This CLK_SRC bit of CTRL(control register) selects the clock source to - the CAN Protocol Interface(CPI) to be either the peripheral clock - (driven by the PLL) or the crystal oscillator clock. The selected clock - is the one fed to the prescaler to generate the Serial Clock (Sclock). - The PRESDIV field of CTRL(control register) controls a prescaler that - generates the Serial Clock (Sclock), whose period defines the - time quantum used to compose the CAN waveform. +- compatible : Should be "fsl,-flexcan" -Can Engine Clock Source - There are two sources for CAN clock - - Platform Clock It represents the bus clock - - Oscillator Clock + An implementation should also claim any of the following compatibles + that it is fully backwards compatible with: - Peripheral Clock (PLL) - -------------- - | - --------- ------------- - | |CPI Clock | Prescaler | Sclock - | |---------------->| (1.. 256) |------------> - --------- ------------- - | | - -------------- ---------------------CLK_SRC - Oscillator Clock + - fsl,p1010-flexcan -- fsl,flexcan-clock-source : CAN Engine Clock Source.This property selects - the peripheral clock. PLL clock is fed to the - prescaler to generate the Serial Clock (Sclock). - Valid values are "oscillator" and "platform" - "oscillator": CAN engine clock source is oscillator clock. - "platform" The CAN engine clock source is the bus clock - (platform clock). +- reg : Offset and length of the register set for this device +- interrupts : Interrupt tuple for this device +- clock-frequency : The oscillator frequency driving the flexcan device -- fsl,flexcan-clock-divider : for the reference and system clock, an additional - clock divider can be specified. -- clock-frequency: frequency required to calculate the bitrate for FlexCAN. +Example: -Note: - - v1.0 of flexcan-v1.0 represent the IP block version for P1010 SOC. - - P1010 does not have oscillator as the Clock Source.So the default - Clock Source is platform clock. -Examples: - - can0@1c000 { - compatible = "fsl,flexcan-v1.0"; + can@1c000 { + compatible = "fsl,p1010-flexcan"; reg = <0x1c000 0x1000>; interrupts = <48 0x2>; interrupt-parent = <&mpic>; - fsl,flexcan-clock-source = "platform"; - fsl,flexcan-clock-divider = <2>; - clock-frequency = ; + clock-frequency = <200000000>; // filled in by bootloader }; diff --git a/Documentation/devicetree/bindings/net/smsc911x.txt b/Documentation/devicetree/bindings/net/smsc911x.txt new file mode 100644 index 0000000000000000000000000000000000000000..adb5b5744ecd6a7809457061721a16479bdc59b2 --- /dev/null +++ b/Documentation/devicetree/bindings/net/smsc911x.txt @@ -0,0 +1,38 @@ +* Smart Mixed-Signal Connectivity (SMSC) LAN911x/912x Controller + +Required properties: +- compatible : Should be "smsc,lan", "smsc,lan9115" +- reg : Address and length of the io space for SMSC LAN +- interrupts : Should contain SMSC LAN interrupt line +- interrupt-parent : Should be the phandle for the interrupt controller + that services interrupts for this device +- phy-mode : String, operation mode of the PHY interface. + Supported values are: "mii", "gmii", "sgmii", "tbi", "rmii", + "rgmii", "rgmii-id", "rgmii-rxid", "rgmii-txid", "rtbi", "smii". + +Optional properties: +- reg-shift : Specify the quantity to shift the register offsets by +- reg-io-width : Specify the size (in bytes) of the IO accesses that + should be performed on the device. Valid value for SMSC LAN is + 2 or 4. If it's omitted or invalid, the size would be 2. +- smsc,irq-active-high : Indicates the IRQ polarity is active-high +- smsc,irq-push-pull : Indicates the IRQ type is push-pull +- smsc,force-internal-phy : Forces SMSC LAN controller to use + internal PHY +- smsc,force-external-phy : Forces SMSC LAN controller to use + external PHY +- smsc,save-mac-address : Indicates that mac address needs to be saved + before resetting the controller +- local-mac-address : 6 bytes, mac address + +Examples: + +lan9220@f4000000 { + compatible = "smsc,lan9220", "smsc,lan9115"; + reg = <0xf4000000 0x2000000>; + phy-mode = "mii"; + interrupt-parent = <&gpio1>; + interrupts = <31>; + reg-io-width = <4>; + smsc,irq-push-pull; +}; diff --git a/Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt b/Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt new file mode 100644 index 0000000000000000000000000000000000000000..36f82dbdd14de47a96d218bcc915adc1365d0788 --- /dev/null +++ b/Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt @@ -0,0 +1,5 @@ +NVIDIA Tegra 2 pinmux controller + +Required properties: +- compatible : "nvidia,tegra20-pinmux" + diff --git a/Documentation/devicetree/bindings/serial/rs485.txt b/Documentation/devicetree/bindings/serial/rs485.txt new file mode 100644 index 0000000000000000000000000000000000000000..1e753c69fc83298249434ecd32543da7b0d929de --- /dev/null +++ b/Documentation/devicetree/bindings/serial/rs485.txt @@ -0,0 +1,31 @@ +* RS485 serial communications + +The RTS signal is capable of automatically controlling line direction for +the built-in half-duplex mode. +The properties described hereafter shall be given to a half-duplex capable +UART node. + +Required properties: +- rs485-rts-delay: prop-encoded-array where: + * a is the delay beteween rts signal and beginning of data sent in milliseconds. + it corresponds to the delay before sending data. + * b is the delay between end of data sent and rts signal in milliseconds + it corresponds to the delay after sending data and actual release of the line. + +Optional properties: +- linux,rs485-enabled-at-boot-time: empty property telling to enable the rs485 + feature at boot time. It can be disabled later with proper ioctl. +- rs485-rx-during-tx: empty property that enables the receiving of data even + whilst sending data. + +RS485 example for Atmel USART: + usart0: serial@fff8c000 { + compatible = "atmel,at91sam9260-usart"; + reg = <0xfff8c000 0x4000>; + interrupts = <7>; + atmel,use-dma-rx; + atmel,use-dma-tx; + linux,rs485-enabled-at-boot-time; + rs485-rts-delay = <0 200>; // in milliseconds + }; + diff --git a/Documentation/devicetree/bindings/sound/soc/codecs/fsl-sgtl5000.txt b/Documentation/devicetree/bindings/sound/soc/codecs/fsl-sgtl5000.txt new file mode 100644 index 0000000000000000000000000000000000000000..2c3cd413f042522ed9877061c728df94bb4f46e8 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/soc/codecs/fsl-sgtl5000.txt @@ -0,0 +1,11 @@ +* Freescale SGTL5000 Stereo Codec + +Required properties: +- compatible : "fsl,sgtl5000". + +Example: + +codec: sgtl5000@0a { + compatible = "fsl,sgtl5000"; + reg = <0x0a>; +}; diff --git a/Documentation/devicetree/bindings/sound/wm8510.txt b/Documentation/devicetree/bindings/sound/wm8510.txt new file mode 100644 index 0000000000000000000000000000000000000000..fa1a32b85577db40322c4ee9655a9da77d983261 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wm8510.txt @@ -0,0 +1,18 @@ +WM8510 audio CODEC + +This device supports both I2C and SPI (configured with pin strapping +on the board). + +Required properties: + + - compatible : "wlf,wm8510" + + - reg : the I2C address of the device for I2C, the chip select + number for SPI. + +Example: + +codec: wm8510@1a { + compatible = "wlf,wm8510"; + reg = <0x1a>; +}; diff --git a/Documentation/devicetree/bindings/sound/wm8523.txt b/Documentation/devicetree/bindings/sound/wm8523.txt new file mode 100644 index 0000000000000000000000000000000000000000..04746186b2831558c7e9f3b27589cbf4d13475da --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wm8523.txt @@ -0,0 +1,16 @@ +WM8523 audio CODEC + +This device supports I2C only. + +Required properties: + + - compatible : "wlf,wm8523" + + - reg : the I2C address of the device. + +Example: + +codec: wm8523@1a { + compatible = "wlf,wm8523"; + reg = <0x1a>; +}; diff --git a/Documentation/devicetree/bindings/sound/wm8580.txt b/Documentation/devicetree/bindings/sound/wm8580.txt new file mode 100644 index 0000000000000000000000000000000000000000..7d9821f348daa689f227ba40eae60784e7fc8e22 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wm8580.txt @@ -0,0 +1,16 @@ +WM8580 audio CODEC + +This device supports I2C only. + +Required properties: + + - compatible : "wlf,wm8580" + + - reg : the I2C address of the device. + +Example: + +codec: wm8580@1a { + compatible = "wlf,wm8580"; + reg = <0x1a>; +}; diff --git a/Documentation/devicetree/bindings/sound/wm8711.txt b/Documentation/devicetree/bindings/sound/wm8711.txt new file mode 100644 index 0000000000000000000000000000000000000000..8ed9998cd23c0ad1f0357152f09b4360d52ec74a --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wm8711.txt @@ -0,0 +1,18 @@ +WM8711 audio CODEC + +This device supports both I2C and SPI (configured with pin strapping +on the board). + +Required properties: + + - compatible : "wlf,wm8711" + + - reg : the I2C address of the device for I2C, the chip select + number for SPI. + +Example: + +codec: wm8711@1a { + compatible = "wlf,wm8711"; + reg = <0x1a>; +}; diff --git a/Documentation/devicetree/bindings/sound/wm8728.txt b/Documentation/devicetree/bindings/sound/wm8728.txt new file mode 100644 index 0000000000000000000000000000000000000000..a8b5c3668e602537faf0bf1189fcd006286af3a4 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wm8728.txt @@ -0,0 +1,18 @@ +WM8728 audio CODEC + +This device supports both I2C and SPI (configured with pin strapping +on the board). + +Required properties: + + - compatible : "wlf,wm8728" + + - reg : the I2C address of the device for I2C, the chip select + number for SPI. + +Example: + +codec: wm8728@1a { + compatible = "wlf,wm8728"; + reg = <0x1a>; +}; diff --git a/Documentation/devicetree/bindings/sound/wm8731.txt b/Documentation/devicetree/bindings/sound/wm8731.txt new file mode 100644 index 0000000000000000000000000000000000000000..15f70048469bdde098a857c6f2566d94ce320d2a --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wm8731.txt @@ -0,0 +1,18 @@ +WM8731 audio CODEC + +This device supports both I2C and SPI (configured with pin strapping +on the board). + +Required properties: + + - compatible : "wlf,wm8731" + + - reg : the I2C address of the device for I2C, the chip select + number for SPI. + +Example: + +codec: wm8731@1a { + compatible = "wlf,wm8731"; + reg = <0x1a>; +}; diff --git a/Documentation/devicetree/bindings/sound/wm8737.txt b/Documentation/devicetree/bindings/sound/wm8737.txt new file mode 100644 index 0000000000000000000000000000000000000000..4bc2cea3b14085cf4b95c62065db7bcdce4e771c --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wm8737.txt @@ -0,0 +1,18 @@ +WM8737 audio CODEC + +This device supports both I2C and SPI (configured with pin strapping +on the board). + +Required properties: + + - compatible : "wlf,wm8737" + + - reg : the I2C address of the device for I2C, the chip select + number for SPI. + +Example: + +codec: wm8737@1a { + compatible = "wlf,wm8737"; + reg = <0x1a>; +}; diff --git a/Documentation/devicetree/bindings/sound/wm8741.txt b/Documentation/devicetree/bindings/sound/wm8741.txt new file mode 100644 index 0000000000000000000000000000000000000000..74bda58c1bcffb01cd1648f605cac031907a5ce3 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wm8741.txt @@ -0,0 +1,18 @@ +WM8741 audio CODEC + +This device supports both I2C and SPI (configured with pin strapping +on the board). + +Required properties: + + - compatible : "wlf,wm8741" + + - reg : the I2C address of the device for I2C, the chip select + number for SPI. + +Example: + +codec: wm8741@1a { + compatible = "wlf,wm8741"; + reg = <0x1a>; +}; diff --git a/Documentation/devicetree/bindings/sound/wm8750.txt b/Documentation/devicetree/bindings/sound/wm8750.txt new file mode 100644 index 0000000000000000000000000000000000000000..8db239fd5ecde354e559e56ef8f32194336a1586 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wm8750.txt @@ -0,0 +1,18 @@ +WM8750 and WM8987 audio CODECs + +These devices support both I2C and SPI (configured with pin strapping +on the board). + +Required properties: + + - compatible : "wlf,wm8750" or "wlf,wm8987" + + - reg : the I2C address of the device for I2C, the chip select + number for SPI. + +Example: + +codec: wm8750@1a { + compatible = "wlf,wm8750"; + reg = <0x1a>; +}; diff --git a/Documentation/devicetree/bindings/sound/wm8753.txt b/Documentation/devicetree/bindings/sound/wm8753.txt new file mode 100644 index 0000000000000000000000000000000000000000..e65277a0fb60dee8b720ef3246cb2ae581f640c7 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wm8753.txt @@ -0,0 +1,18 @@ +WM8753 audio CODEC + +This device supports both I2C and SPI (configured with pin strapping +on the board). + +Required properties: + + - compatible : "wlf,wm8753" + + - reg : the I2C address of the device for I2C, the chip select + number for SPI. + +Example: + +codec: wm8737@1a { + compatible = "wlf,wm8753"; + reg = <0x1a>; +}; diff --git a/Documentation/devicetree/bindings/sound/wm8770.txt b/Documentation/devicetree/bindings/sound/wm8770.txt new file mode 100644 index 0000000000000000000000000000000000000000..866e00ca150b4b04e573e204a3ad39a0c057a58a --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wm8770.txt @@ -0,0 +1,16 @@ +WM8770 audio CODEC + +This device supports SPI. + +Required properties: + + - compatible : "wlf,wm8770" + + - reg : the chip select number. + +Example: + +codec: wm8770@1 { + compatible = "wlf,wm8770"; + reg = <1>; +}; diff --git a/Documentation/devicetree/bindings/sound/wm8776.txt b/Documentation/devicetree/bindings/sound/wm8776.txt new file mode 100644 index 0000000000000000000000000000000000000000..3b9ca49abc2b146a8bacafb0e182b8773b6cb4c3 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wm8776.txt @@ -0,0 +1,18 @@ +WM8776 audio CODEC + +This device supports both I2C and SPI (configured with pin strapping +on the board). + +Required properties: + + - compatible : "wlf,wm8776" + + - reg : the I2C address of the device for I2C, the chip select + number for SPI. + +Example: + +codec: wm8776@1a { + compatible = "wlf,wm8776"; + reg = <0x1a>; +}; diff --git a/Documentation/devicetree/bindings/sound/wm8804.txt b/Documentation/devicetree/bindings/sound/wm8804.txt new file mode 100644 index 0000000000000000000000000000000000000000..4d3a56f38adc31ea6dc24f611c37283fc8898f60 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wm8804.txt @@ -0,0 +1,18 @@ +WM8804 audio CODEC + +This device supports both I2C and SPI (configured with pin strapping +on the board). + +Required properties: + + - compatible : "wlf,wm8804" + + - reg : the I2C address of the device for I2C, the chip select + number for SPI. + +Example: + +codec: wm8804@1a { + compatible = "wlf,wm8804"; + reg = <0x1a>; +}; diff --git a/Documentation/devicetree/bindings/spi/spi_pl022.txt b/Documentation/devicetree/bindings/spi/spi_pl022.txt new file mode 100644 index 0000000000000000000000000000000000000000..306ec3ff3c0e3be27a200ae5fdf215f483fe5eab --- /dev/null +++ b/Documentation/devicetree/bindings/spi/spi_pl022.txt @@ -0,0 +1,12 @@ +ARM PL022 SPI controller + +Required properties: +- compatible : "arm,pl022", "arm,primecell" +- reg : Offset and length of the register set for the device +- interrupts : Should contain SPI controller interrupt + +Optional properties: +- cs-gpios : should specify GPIOs used for chipselects. + The gpios will be referred to as reg = in the SPI child nodes. + If unspecified, a single SPI device without a chip select can be used. + diff --git a/Documentation/devicetree/bindings/tty/serial/atmel-usart.txt b/Documentation/devicetree/bindings/tty/serial/atmel-usart.txt new file mode 100644 index 0000000000000000000000000000000000000000..a49d9a1d4ccf8f054cc1faed657f32095d85a1c3 --- /dev/null +++ b/Documentation/devicetree/bindings/tty/serial/atmel-usart.txt @@ -0,0 +1,27 @@ +* Atmel Universal Synchronous Asynchronous Receiver/Transmitter (USART) + +Required properties: +- compatible: Should be "atmel,-usart" + The compatible indicated will be the first SoC to support an + additional mode or an USART new feature. +- reg: Should contain registers location and length +- interrupts: Should contain interrupt + +Optional properties: +- atmel,use-dma-rx: use of PDC or DMA for receiving data +- atmel,use-dma-tx: use of PDC or DMA for transmitting data + + compatible description: +- at91rm9200: legacy USART support +- at91sam9260: generic USART implementation for SAM9 SoCs + +Example: + + usart0: serial@fff8c000 { + compatible = "atmel,at91sam9260-usart"; + reg = <0xfff8c000 0x4000>; + interrupts = <7>; + atmel,use-dma-rx; + atmel,use-dma-tx; + }; + diff --git a/Documentation/devicetree/bindings/tty/serial/msm_serial.txt b/Documentation/devicetree/bindings/tty/serial/msm_serial.txt new file mode 100644 index 0000000000000000000000000000000000000000..aef383eb8876a470879547a31422fffc2b53859b --- /dev/null +++ b/Documentation/devicetree/bindings/tty/serial/msm_serial.txt @@ -0,0 +1,27 @@ +* Qualcomm MSM UART + +Required properties: +- compatible : + - "qcom,msm-uart", and one of "qcom,msm-hsuart" or + "qcom,msm-lsuart". +- reg : offset and length of the register set for the device + for the hsuart operating in compatible mode, there should be a + second pair describing the gsbi registers. +- interrupts : should contain the uart interrupt. + +There are two different UART blocks used in MSM devices, +"qcom,msm-hsuart" and "qcom,msm-lsuart". The msm-serial driver is +able to handle both of these, and matches against the "qcom,msm-uart" +as the compatibility. + +The registers for the "qcom,msm-hsuart" device need to specify both +register blocks, even for the common driver. + +Example: + + uart@19c400000 { + compatible = "qcom,msm-hsuart", "qcom,msm-uart"; + reg = <0x19c40000 0x1000>, + <0x19c00000 0x1000>; + interrupts = <195>; + }; diff --git a/Documentation/devicetree/bindings/tty/serial/snps-dw-apb-uart.txt b/Documentation/devicetree/bindings/tty/serial/snps-dw-apb-uart.txt new file mode 100644 index 0000000000000000000000000000000000000000..f13f1c5be91cab181bbd97783eef013c7bda1585 --- /dev/null +++ b/Documentation/devicetree/bindings/tty/serial/snps-dw-apb-uart.txt @@ -0,0 +1,25 @@ +* Synopsys DesignWare ABP UART + +Required properties: +- compatible : "snps,dw-apb-uart" +- reg : offset and length of the register set for the device. +- interrupts : should contain uart interrupt. +- clock-frequency : the input clock frequency for the UART. + +Optional properties: +- reg-shift : quantity to shift the register offsets by. If this property is + not present then the register offsets are not shifted. +- reg-io-width : the size (in bytes) of the IO accesses that should be + performed on the device. If this property is not present then single byte + accesses are used. + +Example: + + uart@80230000 { + compatible = "snps,dw-apb-uart"; + reg = <0x80230000 0x100>; + clock-frequency = <3686400>; + interrupts = <10>; + reg-shift = <2>; + reg-io-width = <4>; + }; diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt new file mode 100644 index 0000000000000000000000000000000000000000..e8552782b440af99ed14a6e851e3db5ed47d05fd --- /dev/null +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -0,0 +1,40 @@ +Device tree binding vendor prefix registry. Keep list in alphabetical order. + +This isn't an exhaustive list, but you should add new prefixes to it before +using them to avoid name-space collisions. + +adi Analog Devices, Inc. +amcc Applied Micro Circuits Corporation (APM, formally AMCC) +apm Applied Micro Circuits Corporation (APM) +arm ARM Ltd. +atmel Atmel Corporation +chrp Common Hardware Reference Platform +dallas Maxim Integrated Products (formerly Dallas Semiconductor) +denx Denx Software Engineering +epson Seiko Epson Corp. +est ESTeem Wireless Modems +fsl Freescale Semiconductor +GEFanuc GE Fanuc Intelligent Platforms Embedded Systems, Inc. +gef GE Fanuc Intelligent Platforms Embedded Systems, Inc. +hp Hewlett Packard +ibm International Business Machines (IBM) +idt Integrated Device Technologies, Inc. +intercontrol Inter Control Group +linux Linux-specific binding +marvell Marvell Technology Group Ltd. +maxim Maxim Integrated Products +mosaixtech Mosaix Technologies, Inc. +national National Semiconductor +nintendo Nintendo +nvidia NVIDIA +nxp NXP Semiconductors +powervr Imagination Technologies +qcom Qualcomm, Inc. +ramtron Ramtron International +samsung Samsung Semiconductor +schindler Schindler +simtek +sirf SiRF Technology, Inc. +stericsson ST-Ericsson +ti Texas Instruments +xlnx Xilinx diff --git a/Documentation/driver-model/binding.txt b/Documentation/driver-model/binding.txt index f7ec9d625bfcf78bbe53210a3e649ed921af73cc..abfc8e290d53bb84639b8001179d11f7a696c787 100644 --- a/Documentation/driver-model/binding.txt +++ b/Documentation/driver-model/binding.txt @@ -48,10 +48,6 @@ devclass_add_device is called to enumerate the device within the class and actually register it with the class, which happens with the class's register_dev callback. -NOTE: The device class structures and core routines to manipulate them -are not in the mainline kernel, so the discussion is still a bit -speculative. - Driver ~~~~~~ diff --git a/Documentation/driver-model/device.txt b/Documentation/driver-model/device.txt index bdefe728a737795677b091cbbce14ffed5f27d58..1e70220d20f4fb0ba4ca2bf5a2b3a86e77fe29ce 100644 --- a/Documentation/driver-model/device.txt +++ b/Documentation/driver-model/device.txt @@ -45,33 +45,52 @@ struct device_attribute { const char *buf, size_t count); }; -Attributes of devices can be exported via drivers using a simple -procfs-like interface. +Attributes of devices can be exported by a device driver through sysfs. Please see Documentation/filesystems/sysfs.txt for more information on how sysfs works. +As explained in Documentation/kobject.txt, device attributes must be be +created before the KOBJ_ADD uevent is generated. The only way to realize +that is by defining an attribute group. + Attributes are declared using a macro called DEVICE_ATTR: #define DEVICE_ATTR(name,mode,show,store) Example: -DEVICE_ATTR(power,0644,show_power,store_power); +static DEVICE_ATTR(type, 0444, show_type, NULL); +static DEVICE_ATTR(power, 0644, show_power, store_power); -This declares a structure of type struct device_attribute named -'dev_attr_power'. This can then be added and removed to the device's -directory using: +This declares two structures of type struct device_attribute with respective +names 'dev_attr_type' and 'dev_attr_power'. These two attributes can be +organized as follows into a group: -int device_create_file(struct device *device, struct device_attribute * entry); -void device_remove_file(struct device * dev, struct device_attribute * attr); +static struct attribute *dev_attrs[] = { + &dev_attr_type.attr, + &dev_attr_power.attr, + NULL, +}; -Example: +static struct attribute_group dev_attr_group = { + .attrs = dev_attrs, +}; + +static const struct attribute_group *dev_attr_groups[] = { + &dev_attr_group, + NULL, +}; + +This array of groups can then be associated with a device by setting the +group pointer in struct device before device_register() is invoked: -device_create_file(dev,&dev_attr_power); -device_remove_file(dev,&dev_attr_power); + dev->groups = dev_attr_groups; + device_register(dev); -The file name will be 'power' with a mode of 0644 (-rw-r--r--). +The device_register() function will use the 'groups' pointer to create the +device attributes and the device_unregister() function will use this pointer +to remove the device attributes. Word of warning: While the kernel allows device_create_file() and device_remove_file() to be called on a device at any time, userspace has @@ -84,24 +103,4 @@ not know about the new attributes. This is important for device driver that need to publish additional attributes for a device at driver probe time. If the device driver simply calls device_create_file() on the device structure passed to it, then -userspace will never be notified of the new attributes. Instead, it should -probably use class_create() and class->dev_attrs to set up a list of -desired attributes in the modules_init function, and then in the .probe() -hook, and then use device_create() to create a new device as a child -of the probed device. The new device will generate a new uevent and -properly advertise the new attributes to userspace. - -For example, if a driver wanted to add the following attributes: -struct device_attribute mydriver_attribs[] = { - __ATTR(port_count, 0444, port_count_show), - __ATTR(serial_number, 0444, serial_number_show), - NULL -}; - -Then in the module init function is would do: - mydriver_class = class_create(THIS_MODULE, "my_attrs"); - mydriver_class.dev_attr = mydriver_attribs; - -And assuming 'dev' is the struct device passed into the probe hook, the driver -probe function would do something like: - device_create(&mydriver_class, dev, chrdev, &private_data, "my_name"); +userspace will never be notified of the new attributes. diff --git a/Documentation/dvb/get_dvb_firmware b/Documentation/dvb/get_dvb_firmware index c466f5831f15040912e447b70a9cc196cab9cfb7..e67be7afc78b481d4dc42553bc555690e34c898e 100755 --- a/Documentation/dvb/get_dvb_firmware +++ b/Documentation/dvb/get_dvb_firmware @@ -27,7 +27,8 @@ use IO::Handle; "or51211", "or51132_qam", "or51132_vsb", "bluebird", "opera1", "cx231xx", "cx18", "cx23885", "pvrusb2", "mpc718", "af9015", "ngene", "az6027", "lme2510_lg", "lme2510c_s7395", - "lme2510c_s7395_old", "drxk", "drxk_terratec_h5"); + "lme2510c_s7395_old", "drxk", "drxk_terratec_h5", "tda10071", + "it9135" ); # Check args syntax() if (scalar(@ARGV) != 1); @@ -575,19 +576,10 @@ sub ngene { } sub az6027{ - my $file = "AZ6027_Linux_Driver.tar.gz"; - my $url = "http://linux.terratec.de/files/$file"; my $firmware = "dvb-usb-az6027-03.fw"; + my $url = "http://linux.terratec.de/files/TERRATEC_S7/$firmware"; - wgetfile($file, $url); - - #untar - if( system("tar xzvf $file $firmware")){ - die "failed to untar firmware"; - } - if( system("rm $file")){ - die ("unable to remove unnecessary files"); - } + wgetfile($firmware, $url); $firmware; } @@ -665,6 +657,41 @@ sub drxk_terratec_h5 { "$fwfile" } +sub it9135 { + my $url = "http://kworld.server261.com/kworld/CD/ITE_TiVme/V1.00/"; + my $zipfile = "Driver_V10.323.1.0412.100412.zip"; + my $hash = "79b597dc648698ed6820845c0c9d0d37"; + my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 0); + my $drvfile = "Driver_V10.323.1.0412.100412/Data/x86/IT9135BDA.sys"; + my $fwfile = "dvb-usb-it9137-01.fw"; + + checkstandard(); + + wgetfile($zipfile, $url . $zipfile); + verify($zipfile, $hash); + unzip($zipfile, $tmpdir); + extract("$tmpdir/$drvfile", 69632, 5731, "$fwfile"); + + "$fwfile" +} + +sub tda10071 { + my $sourcefile = "PCTV_460e_reference.zip"; + my $url = "ftp://ftp.pctvsystems.com/TV/driver/PCTV%2070e%2080e%20100e%20320e%20330e%20800e/"; + my $hash = "4403de903bf2593464c8d74bbc200a57"; + my $fwfile = "dvb-fe-tda10071.fw"; + my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); + + checkstandard(); + + wgetfile($sourcefile, $url . $sourcefile); + verify($sourcefile, $hash); + unzip($sourcefile, $tmpdir); + extract("$tmpdir/PCTV\ 70e\ 80e\ 100e\ 320e\ 330e\ 800e/32\ bit/emOEM.sys", 0x67d38, 40504, $fwfile); + + "$fwfile"; +} + # --------------------------------------------------------------- # Utilities diff --git a/Documentation/dvb/it9137.txt b/Documentation/dvb/it9137.txt new file mode 100644 index 0000000000000000000000000000000000000000..9e6726eead906f6315b782c3f77fe1f49cba8e83 --- /dev/null +++ b/Documentation/dvb/it9137.txt @@ -0,0 +1,9 @@ +To extract firmware for Kworld UB499-2T (id 1b80:e409) you need to copy the +following file(s) to this directory. + +IT9135BDA.sys Dated Mon 22 Mar 2010 02:20:08 GMT + +extract using dd +dd if=IT9135BDA.sys ibs=1 skip=69632 count=5731 of=dvb-usb-it9137-01.fw + +copy to default firmware location. diff --git a/Documentation/fault-injection/fault-injection.txt b/Documentation/fault-injection/fault-injection.txt index 82a5d250d75e705f92b8c32ff634ca1b945ef008..ba4be8b77093f2ea0399ae7c6662471e987a98e0 100644 --- a/Documentation/fault-injection/fault-injection.txt +++ b/Documentation/fault-injection/fault-injection.txt @@ -21,6 +21,11 @@ o fail_make_request /sys/block//make-it-fail or /sys/block///make-it-fail. (generic_make_request()) +o fail_mmc_request + + injects MMC data errors on devices permitted by setting + debugfs entries under /sys/kernel/debug/mmc0/fail_mmc_request + Configure fault-injection capabilities behavior ----------------------------------------------- @@ -115,7 +120,8 @@ use the boot option: failslab= fail_page_alloc= - fail_make_request=,,, + fail_make_request= + mmc_core.fail_request=,,, How to add new fault injection capability ----------------------------------------- diff --git a/Documentation/fb/udlfb.txt b/Documentation/fb/udlfb.txt index 7fdde2a02a27be74e7e45508e449b5376b28abca..57d2f2908b12bcb01eae4669e3f0d50eeabf9d7e 100644 --- a/Documentation/fb/udlfb.txt +++ b/Documentation/fb/udlfb.txt @@ -87,23 +87,38 @@ Special configuration for udlfb is usually unnecessary. There are a few options, however. From the command line, pass options to modprobe -modprobe udlfb defio=1 console=1 +modprobe udlfb fb_defio=0 console=1 shadow=1 -Or for permanent option, create file like /etc/modprobe.d/options with text -options udlfb defio=1 console=1 +Or modify options on the fly at /sys/module/udlfb/parameters directory via +sudo nano fb_defio +change the parameter in place, and save the file. -Accepted options: +Unplug/replug USB device to apply with new settings + +Or for permanent option, create file like /etc/modprobe.d/udlfb.conf with text +options udlfb fb_defio=0 console=1 shadow=1 + +Accepted boolean options: fb_defio Make use of the fb_defio (CONFIG_FB_DEFERRED_IO) kernel module to track changed areas of the framebuffer by page faults. - Standard fbdev applications that use mmap but that do not - report damage, may be able to work with this enabled. - Disabled by default because of overhead and other issues. - -console Allow fbcon to attach to udlfb provided framebuffers. This - is disabled by default because fbcon will aggressively consume - the first framebuffer it finds, which isn't usually what the - user wants in the case of USB displays. + Standard fbdev applications that use mmap but that do not + report damage, should be able to work with this enabled. + Disable when running with X server that supports reporting + changed regions via ioctl, as this method is simpler, + more stable, and higher performance. + default: fb_defio=1 + +console Allow fbcon to attach to udlfb provided framebuffers. + Can be disabled if fbcon and other clients + (e.g. X with --shared-vt) are in conflict. + default: console=1 + +shadow Allocate a 2nd framebuffer to shadow what's currently across + the USB bus in device memory. If any pixels are unchanged, + do not transmit. Spends host memory to save USB transfers. + Enabled by default. Only disable on very low memory systems. + default: shadow=1 Sysfs Attributes ================ diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 4dc4654776657b68f35161ac642e9caa187d15e4..7c799fc5b88e3525e611066d7be26c06226fd3db 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -495,29 +495,6 @@ Who: Jean Delvare ---------------------------- -What: Support for UVCIOC_CTRL_ADD in the uvcvideo driver -When: 3.2 -Why: The information passed to the driver by this ioctl is now queried - dynamically from the device. -Who: Laurent Pinchart - ----------------------------- - -What: Support for UVCIOC_CTRL_MAP_OLD in the uvcvideo driver -When: 3.2 -Why: Used only by applications compiled against older driver versions. - Superseded by UVCIOC_CTRL_MAP which supports V4L2 menu controls. -Who: Laurent Pinchart - ----------------------------- - -What: Support for UVCIOC_CTRL_GET and UVCIOC_CTRL_SET in the uvcvideo driver -When: 3.2 -Why: Superseded by the UVCIOC_CTRL_QUERY ioctl. -Who: Laurent Pinchart - ----------------------------- - What: Support for driver specific ioctls in the pwc driver (everything defined in media/pwc-ioctl.h) When: 3.3 @@ -594,9 +571,18 @@ Why: In 3.0, we can now autodetect internal 3G device and already have Who: Lee, Chun-Yi ---------------------------- + What: The XFS nodelaylog mount option When: 3.3 Why: The delaylog mode that has been the default since 2.6.39 has proven stable, and the old code is in the way of additional improvements in the log code. Who: Christoph Hellwig + +---------------------------- + +What: iwlagn alias support +When: 3.5 +Why: The iwlagn module has been renamed iwlwifi. The alias will be around + for backward compatibility for several cycles and then dropped. +Who: Don Fry diff --git a/Documentation/filesystems/9p.txt b/Documentation/filesystems/9p.txt index 13de64c7f0ab0bf7f347156573e187a0a72ac4a0..2c0321442845525c44273b2759cf0912b75037f8 100644 --- a/Documentation/filesystems/9p.txt +++ b/Documentation/filesystems/9p.txt @@ -92,7 +92,7 @@ OPTIONS wfdno=n the file descriptor for writing with trans=fd - maxdata=n the number of bytes to use for 9p packet payload (msize) + msize=n the number of bytes to use for 9p packet payload port=n port to connect to on the remote server diff --git a/Documentation/filesystems/caching/object.txt b/Documentation/filesystems/caching/object.txt index e8b0a35d8fe577395f2508b0bfbbf47250d94ee0..58313348da870ec0a0dda2c6190354593352f7fc 100644 --- a/Documentation/filesystems/caching/object.txt +++ b/Documentation/filesystems/caching/object.txt @@ -127,9 +127,9 @@ fscache_enqueue_object()). PROVISION OF CPU TIME --------------------- -The work to be done by the various states is given CPU time by the threads of -the slow work facility (see Documentation/slow-work.txt). This is used in -preference to the workqueue facility because: +The work to be done by the various states was given CPU time by the threads of +the slow work facility. This was used in preference to the workqueue facility +because: (1) Threads may be completely occupied for very long periods of time by a particular work item. These state actions may be doing sequences of diff --git a/Documentation/filesystems/locks.txt b/Documentation/filesystems/locks.txt index fab857accbd63c48d5fb6a93f56398e249e00e8f..2cf81082581dbca9cc6cb0d046fcd1c7725e1d74 100644 --- a/Documentation/filesystems/locks.txt +++ b/Documentation/filesystems/locks.txt @@ -53,11 +53,12 @@ fcntl(), with all the problems that implies. 1.3 Mandatory Locking As A Mount Option --------------------------------------- -Mandatory locking, as described in 'Documentation/filesystems/mandatory.txt' -was prior to this release a general configuration option that was valid for -all mounted filesystems. This had a number of inherent dangers, not the -least of which was the ability to freeze an NFS server by asking it to read -a file for which a mandatory lock existed. +Mandatory locking, as described in +'Documentation/filesystems/mandatory-locking.txt' was prior to this release a +general configuration option that was valid for all mounted filesystems. This +had a number of inherent dangers, not the least of which was the ability to +freeze an NFS server by asking it to read a file for which a mandatory lock +existed. From this release of the kernel, mandatory locking can be turned on and off on a per-filesystem basis, using the mount options 'mand' and 'nomand'. diff --git a/Documentation/filesystems/nfs/idmapper.txt b/Documentation/filesystems/nfs/idmapper.txt index 9c8fd614865642e7b9faf418de164c6088204b50..120fd3cf7fd92b666cfcf7ea8eda236e01e22282 100644 --- a/Documentation/filesystems/nfs/idmapper.txt +++ b/Documentation/filesystems/nfs/idmapper.txt @@ -47,7 +47,7 @@ request-key will find the first matching line and corresponding program. In this case, /some/other/program will handle all uid lookups and /usr/sbin/nfs.idmap will handle gid, user, and group lookups. -See for more information +See for more information about the request-key function. diff --git a/Documentation/filesystems/pohmelfs/design_notes.txt b/Documentation/filesystems/pohmelfs/design_notes.txt index dcf8335871628a950a6173ae9caa15ee67e4f34f..8aef91335701ce1e5b0ca54d3a6b3bd8abd47bbe 100644 --- a/Documentation/filesystems/pohmelfs/design_notes.txt +++ b/Documentation/filesystems/pohmelfs/design_notes.txt @@ -58,8 +58,9 @@ data transfers. POHMELFS clients operate with a working set of servers and are capable of balancing read-only operations (like lookups or directory listings) between them according to IO priorities. Administrators can add or remove servers from the set at run-time via special commands (described -in Documentation/pohmelfs/info.txt file). Writes are replicated to all servers, which are connected -with write permission turned on. IO priority and permissions can be changed in run-time. +in Documentation/filesystems/pohmelfs/info.txt file). Writes are replicated to all servers, which +are connected with write permission turned on. IO priority and permissions can be changed in +run-time. POHMELFS is capable of full data channel encryption and/or strong crypto hashing. One can select any kernel supported cipher, encryption mode, hash type and operation mode diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index db3b1aba32a3f9c0d80ce0cde2d8b6f1943f4dea..0ec91f03422e5befe8dd7f69d22dec4a22250f69 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -1263,7 +1263,7 @@ review the kernel documentation in the directory /usr/src/linux/Documentation. This chapter is heavily based on the documentation included in the pre 2.2 kernels, and became part of it in version 2.2.1 of the Linux kernel. -Please see: Documentation/sysctls/ directory for descriptions of these +Please see: Documentation/sysctl/ directory for descriptions of these entries. ------------------------------------------------------------------------------ diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt index 597f728e7b4e9d4c2e9ec231c166be3f1d277642..07235caec22c6ef811af210aff63857c25f9dd56 100644 --- a/Documentation/filesystems/sysfs.txt +++ b/Documentation/filesystems/sysfs.txt @@ -4,7 +4,7 @@ sysfs - _The_ filesystem for exporting kernel objects. Patrick Mochel Mike Murphy -Revised: 15 July 2010 +Revised: 16 August 2011 Original: 10 January 2003 @@ -370,3 +370,11 @@ int driver_create_file(struct device_driver *, const struct driver_attribute *); void driver_remove_file(struct device_driver *, const struct driver_attribute *); +Documentation +~~~~~~~~~~~~~ + +The sysfs directory structure and the attributes in each directory define an +ABI between the kernel and user space. As for any ABI, it is important that +this ABI is stable and properly documented. All new sysfs attributes must be +documented in Documentation/ABI. See also Documentation/ABI/README for more +information. diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index 52d8fb81cffffdffe3cb8f4ddb1cd65d586855fb..43cbd0821721ae299ebface2865ffb17b3170fde 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -1053,9 +1053,6 @@ manipulate dentries: and the dentry is returned. The caller must use dput() to free the dentry when it finishes using it. -For further information on dentry locking, please refer to the document -Documentation/filesystems/dentry-locking.txt. - Mount Options ============= diff --git a/Documentation/frv/booting.txt b/Documentation/frv/booting.txt index 37c4d84a0e570240222ea08d95b0fb79280c29f3..9bdf4b46e741e869f9a32e8afd121a7efa1e2dab 100644 --- a/Documentation/frv/booting.txt +++ b/Documentation/frv/booting.txt @@ -180,9 +180,3 @@ separated by spaces: This tells the kernel what program to run initially. By default this is /sbin/init, but /sbin/sash or /bin/sh are common alternatives. - - (*) vdc=... - - This option configures the MB93493 companion chip visual display - driver. Please see Documentation/frv/mb93493/vdc.txt for more - information. diff --git a/Documentation/hwmon/ad7314 b/Documentation/hwmon/ad7314 new file mode 100644 index 0000000000000000000000000000000000000000..1912549c7467eddd199ce6d56359eec1c41f9195 --- /dev/null +++ b/Documentation/hwmon/ad7314 @@ -0,0 +1,25 @@ +Kernel driver ad7314 +==================== + +Supported chips: + * Analog Devices AD7314 + Prefix: 'ad7314' + Datasheet: Publicly available at Analog Devices website. + * Analog Devices ADT7301 + Prefix: 'adt7301' + Datasheet: Publicly available at Analog Devices website. + * Analog Devices ADT7302 + Prefix: 'adt7302' + Datasheet: Publicly available at Analog Devices website. + +Description +----------- + +Driver supports the above parts. The ad7314 has a 10 bit +sensor with 1lsb = 0.25 degrees centigrade. The adt7301 and +adt7302 have 14 bit sensors with 1lsb = 0.03125 degrees centigrade. + +Notes +----- + +Currently power down mode is not supported. diff --git a/Documentation/hwmon/adm1275 b/Documentation/hwmon/adm1275 index 097b3ccc4be767fd02a8c205e09812ed8982c5d5..ab70d96d2dfd5fdb583359bb6fed0aee3ebee4ce 100644 --- a/Documentation/hwmon/adm1275 +++ b/Documentation/hwmon/adm1275 @@ -6,6 +6,10 @@ Supported chips: Prefix: 'adm1275' Addresses scanned: - Datasheet: www.analog.com/static/imported-files/data_sheets/ADM1275.pdf + * Analog Devices ADM1276 + Prefix: 'adm1276' + Addresses scanned: - + Datasheet: www.analog.com/static/imported-files/data_sheets/ADM1276.pdf Author: Guenter Roeck @@ -13,13 +17,13 @@ Author: Guenter Roeck Description ----------- -This driver supports hardware montoring for Analog Devices ADM1275 Hot-Swap -Controller and Digital Power Monitor. +This driver supports hardware montoring for Analog Devices ADM1275 and ADM1276 +Hot-Swap Controller and Digital Power Monitor. -The ADM1275 is a hot-swap controller that allows a circuit board to be removed -from or inserted into a live backplane. It also features current and voltage -readback via an integrated 12-bit analog-to-digital converter (ADC), accessed -using a PMBus. interface. +ADM1275 and ADM1276 are hot-swap controllers that allow a circuit board to be +removed from or inserted into a live backplane. They also feature current and +voltage readback via an integrated 12-bit analog-to-digital converter (ADC), +accessed using a PMBus interface. The driver is a client driver to the core PMBus driver. Please see Documentation/hwmon/pmbus for details on PMBus client drivers. @@ -48,17 +52,25 @@ attributes are write-only, all other attributes are read-only. in1_label "vin1" or "vout1" depending on chip variant and configuration. -in1_input Measured voltage. From READ_VOUT register. -in1_min Minumum Voltage. From VOUT_UV_WARN_LIMIT register. -in1_max Maximum voltage. From VOUT_OV_WARN_LIMIT register. -in1_min_alarm Voltage low alarm. From VOLTAGE_UV_WARNING status. -in1_max_alarm Voltage high alarm. From VOLTAGE_OV_WARNING status. +in1_input Measured voltage. +in1_min Minumum Voltage. +in1_max Maximum voltage. +in1_min_alarm Voltage low alarm. +in1_max_alarm Voltage high alarm. in1_highest Historical maximum voltage. in1_reset_history Write any value to reset history. curr1_label "iout1" -curr1_input Measured current. From READ_IOUT register. -curr1_max Maximum current. From IOUT_OC_WARN_LIMIT register. -curr1_max_alarm Current high alarm. From IOUT_OC_WARN_LIMIT register. +curr1_input Measured current. +curr1_max Maximum current. +curr1_max_alarm Current high alarm. +curr1_lcrit Critical minimum current. Depending on the chip + configuration, either curr1_lcrit or curr1_crit is + supported, but not both. +curr1_lcrit_alarm Critical current low alarm. +curr1_crit Critical maximum current. Depending on the chip + configuration, either curr1_lcrit or curr1_crit is + supported, but not both. +curr1_crit_alarm Critical current high alarm. curr1_highest Historical maximum current. curr1_reset_history Write any value to reset history. diff --git a/Documentation/hwmon/exynos4_tmu b/Documentation/hwmon/exynos4_tmu new file mode 100644 index 0000000000000000000000000000000000000000..c3c6b41db607112d1502feb1b1fb36ed75da2b95 --- /dev/null +++ b/Documentation/hwmon/exynos4_tmu @@ -0,0 +1,81 @@ +Kernel driver exynos4_tmu +================= + +Supported chips: +* ARM SAMSUNG EXYNOS4 series of SoC + Prefix: 'exynos4-tmu' + Datasheet: Not publicly available + +Authors: Donggeun Kim + +Description +----------- + +This driver allows to read temperature inside SAMSUNG EXYNOS4 series of SoC. + +The chip only exposes the measured 8-bit temperature code value +through a register. +Temperature can be taken from the temperature code. +There are three equations converting from temperature to temperature code. + +The three equations are: + 1. Two point trimming + Tc = (T - 25) * (TI2 - TI1) / (85 - 25) + TI1 + + 2. One point trimming + Tc = T + TI1 - 25 + + 3. No trimming + Tc = T + 50 + + Tc: Temperature code, T: Temperature, + TI1: Trimming info for 25 degree Celsius (stored at TRIMINFO register) + Temperature code measured at 25 degree Celsius which is unchanged + TI2: Trimming info for 85 degree Celsius (stored at TRIMINFO register) + Temperature code measured at 85 degree Celsius which is unchanged + +TMU(Thermal Management Unit) in EXYNOS4 generates interrupt +when temperature exceeds pre-defined levels. +The maximum number of configurable threshold is four. +The threshold levels are defined as follows: + Level_0: current temperature > trigger_level_0 + threshold + Level_1: current temperature > trigger_level_1 + threshold + Level_2: current temperature > trigger_level_2 + threshold + Level_3: current temperature > trigger_level_3 + threshold + + The threshold and each trigger_level are set + through the corresponding registers. + +When an interrupt occurs, this driver notify user space of +one of four threshold levels for the interrupt +through kobject_uevent_env and sysfs_notify functions. +Although an interrupt condition for level_0 can be set, +it is not notified to user space through sysfs_notify function. + +Sysfs Interface +--------------- +name name of the temperature sensor + RO + +temp1_input temperature + RO + +temp1_max temperature for level_1 interrupt + RO + +temp1_crit temperature for level_2 interrupt + RO + +temp1_emergency temperature for level_3 interrupt + RO + +temp1_max_alarm alarm for level_1 interrupt + RO + +temp1_crit_alarm + alarm for level_2 interrupt + RO + +temp1_emergency_alarm + alarm for level_3 interrupt + RO diff --git a/Documentation/hwmon/lm75 b/Documentation/hwmon/lm75 index a1790401fddee6bed131867878257b2004a91989..c91a1d15fa28ae62aca3796ab89e15de3fdd0f5a 100644 --- a/Documentation/hwmon/lm75 +++ b/Documentation/hwmon/lm75 @@ -12,26 +12,46 @@ Supported chips: Addresses scanned: I2C 0x48 - 0x4f Datasheet: Publicly available at the National Semiconductor website http://www.national.com/ - * Dallas Semiconductor DS75 - Prefix: 'lm75' - Addresses scanned: I2C 0x48 - 0x4f - Datasheet: Publicly available at the Dallas Semiconductor website - http://www.maxim-ic.com/ - * Dallas Semiconductor DS1775 - Prefix: 'lm75' - Addresses scanned: I2C 0x48 - 0x4f + * Dallas Semiconductor DS75, DS1775 + Prefixes: 'ds75', 'ds1775' + Addresses scanned: none Datasheet: Publicly available at the Dallas Semiconductor website http://www.maxim-ic.com/ * Maxim MAX6625, MAX6626 - Prefix: 'lm75' - Addresses scanned: I2C 0x48 - 0x4b + Prefixes: 'max6625', 'max6626' + Addresses scanned: none Datasheet: Publicly available at the Maxim website http://www.maxim-ic.com/ * Microchip (TelCom) TCN75 Prefix: 'lm75' - Addresses scanned: I2C 0x48 - 0x4f + Addresses scanned: none + Datasheet: Publicly available at the Microchip website + http://www.microchip.com/ + * Microchip MCP9800, MCP9801, MCP9802, MCP9803 + Prefix: 'mcp980x' + Addresses scanned: none Datasheet: Publicly available at the Microchip website http://www.microchip.com/ + * Analog Devices ADT75 + Prefix: 'adt75' + Addresses scanned: none + Datasheet: Publicly available at the Analog Devices website + http://www.analog.com/adt75 + * ST Microelectronics STDS75 + Prefix: 'stds75' + Addresses scanned: none + Datasheet: Publicly available at the ST website + http://www.st.com/internet/analog/product/121769.jsp + * Texas Instruments TMP100, TMP101, TMP105, TMP75, TMP175, TMP275 + Prefixes: 'tmp100', 'tmp101', 'tmp105', 'tmp175', 'tmp75', 'tmp275' + Addresses scanned: none + Datasheet: Publicly available at the Texas Instruments website + http://www.ti.com/product/tmp100 + http://www.ti.com/product/tmp101 + http://www.ti.com/product/tmp105 + http://www.ti.com/product/tmp75 + http://www.ti.com/product/tmp175 + http://www.ti.com/product/tmp275 Author: Frodo Looijaard @@ -50,21 +70,16 @@ range of -55 to +125 degrees. The LM75 only updates its values each 1.5 seconds; reading it more often will do no harm, but will return 'old' values. -The LM75 is usually used in combination with LM78-like chips, to measure -the temperature of the processor(s). - -The DS75, DS1775, MAX6625, and MAX6626 are supported as well. -They are not distinguished from an LM75. While most of these chips -have three additional bits of accuracy (12 vs. 9 for the LM75), -the additional bits are not supported. Not only that, but these chips will -not be detected if not in 9-bit precision mode (use the force parameter if -needed). - -The TCN75 is supported as well, and is not distinguished from an LM75. +The original LM75 was typically used in combination with LM78-like chips +on PC motherboards, to measure the temperature of the processor(s). Clones +are now used in various embedded designs. The LM75 is essentially an industry standard; there may be other LM75 clones not listed here, with or without various enhancements, -that are supported. +that are supported. The clones are not detected by the driver, unless +they reproduce the exact register tricks of the original LM75, and must +therefore be instantiated explicitly. The specific enhancements (such as +higher resolution) are not currently supported by the driver. The LM77 is not supported, contrary to what we pretended for a long time. Both chips are simply not compatible, value encoding differs. diff --git a/Documentation/hwmon/ltc2978 b/Documentation/hwmon/ltc2978 new file mode 100644 index 0000000000000000000000000000000000000000..c365f9beb5dd6a1657fbcbbb38f2298aba204b73 --- /dev/null +++ b/Documentation/hwmon/ltc2978 @@ -0,0 +1,103 @@ +Kernel driver ltc2978 +===================== + +Supported chips: + * Linear Technology LTC2978 + Prefix: 'ltc2978' + Addresses scanned: - + Datasheet: http://cds.linear.com/docs/Datasheet/2978fa.pdf + * Linear Technology LTC3880 + Prefix: 'ltc3880' + Addresses scanned: - + Datasheet: http://cds.linear.com/docs/Datasheet/3880f.pdf + +Author: Guenter Roeck + + +Description +----------- + +The LTC2978 is an octal power supply monitor, supervisor, sequencer and +margin controller. The LTC3880 is a dual, PolyPhase DC/DC synchronous +step-down switching regulator controller. + + +Usage Notes +----------- + +This driver does not probe for PMBus devices. You will have to instantiate +devices explicitly. + +Example: the following commands will load the driver for an LTC2978 at address +0x60 on I2C bus #1: + +# modprobe ltc2978 +# echo ltc2978 0x60 > /sys/bus/i2c/devices/i2c-1/new_device + + +Sysfs attributes +---------------- + +in1_label "vin" +in1_input Measured input voltage. +in1_min Minimum input voltage. +in1_max Maximum input voltage. +in1_lcrit Critical minimum input voltage. +in1_crit Critical maximum input voltage. +in1_min_alarm Input voltage low alarm. +in1_max_alarm Input voltage high alarm. +in1_lcrit_alarm Input voltage critical low alarm. +in1_crit_alarm Input voltage critical high alarm. +in1_lowest Lowest input voltage. LTC2978 only. +in1_highest Highest input voltage. +in1_reset_history Reset history. Writing into this attribute will reset + history for all attributes. + +in[2-9]_label "vout[1-8]". Channels 3 to 9 on LTC2978 only. +in[2-9]_input Measured output voltage. +in[2-9]_min Minimum output voltage. +in[2-9]_max Maximum output voltage. +in[2-9]_lcrit Critical minimum output voltage. +in[2-9]_crit Critical maximum output voltage. +in[2-9]_min_alarm Output voltage low alarm. +in[2-9]_max_alarm Output voltage high alarm. +in[2-9]_lcrit_alarm Output voltage critical low alarm. +in[2-9]_crit_alarm Output voltage critical high alarm. +in[2-9]_lowest Lowest output voltage. LTC2978 only. +in[2-9]_highest Lowest output voltage. +in[2-9]_reset_history Reset history. Writing into this attribute will reset + history for all attributes. + +temp[1-3]_input Measured temperature. + On LTC2978, only one temperature measurement is + supported and reflects the internal temperature. + On LTC3880, temp1 and temp2 report external + temperatures, and temp3 reports the internal + temperature. +temp[1-3]_min Mimimum temperature. +temp[1-3]_max Maximum temperature. +temp[1-3]_lcrit Critical low temperature. +temp[1-3]_crit Critical high temperature. +temp[1-3]_min_alarm Chip temperature low alarm. +temp[1-3]_max_alarm Chip temperature high alarm. +temp[1-3]_lcrit_alarm Chip temperature critical low alarm. +temp[1-3]_crit_alarm Chip temperature critical high alarm. +temp[1-3]_lowest Lowest measured temperature. LTC2978 only. +temp[1-3]_highest Highest measured temperature. +temp[1-3]_reset_history Reset history. Writing into this attribute will reset + history for all attributes. + +power[1-2]_label "pout[1-2]". LTC3880 only. +power[1-2]_input Measured power. + +curr1_label "iin". LTC3880 only. +curr1_input Measured input current. +curr1_max Maximum input current. +curr1_max_alarm Input current high alarm. + +curr[2-3]_label "iout[1-2]". LTC3880 only. +curr[2-3]_input Measured input current. +curr[2-3]_max Maximum input current. +curr[2-3]_crit Critical input current. +curr[2-3]_max_alarm Input current high alarm. +curr[2-3]_crit_alarm Input current critical high alarm. diff --git a/Documentation/hwmon/pmbus b/Documentation/hwmon/pmbus index c36c1c1a62bb3915ea47cb865c970720825d0ce3..15ac911ce51bdbad2840b8367c55a44d490e4a27 100644 --- a/Documentation/hwmon/pmbus +++ b/Documentation/hwmon/pmbus @@ -8,11 +8,6 @@ Supported chips: Addresses scanned: - Datasheet: http://archive.ericsson.net/service/internet/picov/get?DocNo=28701-EN/LZT146395 - * Linear Technology LTC2978 - Octal PMBus Power Supply Monitor and Controller - Prefix: 'ltc2978' - Addresses scanned: - - Datasheet: http://cds.linear.com/docs/Datasheet/2978fa.pdf * ON Semiconductor ADP4000, NCP4200, NCP4208 Prefixes: 'adp4000', 'ncp4200', 'ncp4208' Addresses scanned: - @@ -20,6 +15,14 @@ Supported chips: http://www.onsemi.com/pub_link/Collateral/ADP4000-D.PDF http://www.onsemi.com/pub_link/Collateral/NCP4200-D.PDF http://www.onsemi.com/pub_link/Collateral/JUNE%202009-%20REV.%200.PDF + * Lineage Power + Prefixes: 'pdt003', 'pdt006', 'pdt012', 'udt020' + Addresses scanned: - + Datasheets: + http://www.lineagepower.com/oem/pdf/PDT003A0X.pdf + http://www.lineagepower.com/oem/pdf/PDT006A0X.pdf + http://www.lineagepower.com/oem/pdf/PDT012A0X.pdf + http://www.lineagepower.com/oem/pdf/UDT020A0X.pdf * Generic PMBus devices Prefix: 'pmbus' Addresses scanned: - diff --git a/Documentation/hwmon/pmbus-core b/Documentation/hwmon/pmbus-core new file mode 100644 index 0000000000000000000000000000000000000000..31e4720fed18c7f8bb8901c0621720f62bc56375 --- /dev/null +++ b/Documentation/hwmon/pmbus-core @@ -0,0 +1,283 @@ +PMBus core driver and internal API +================================== + +Introduction +============ + +[from pmbus.org] The Power Management Bus (PMBus) is an open standard +power-management protocol with a fully defined command language that facilitates +communication with power converters and other devices in a power system. The +protocol is implemented over the industry-standard SMBus serial interface and +enables programming, control, and real-time monitoring of compliant power +conversion products. This flexible and highly versatile standard allows for +communication between devices based on both analog and digital technologies, and +provides true interoperability which will reduce design complexity and shorten +time to market for power system designers. Pioneered by leading power supply and +semiconductor companies, this open power system standard is maintained and +promoted by the PMBus Implementers Forum (PMBus-IF), comprising 30+ adopters +with the objective to provide support to, and facilitate adoption among, users. + +Unfortunately, while PMBus commands are standardized, there are no mandatory +commands, and manufacturers can add as many non-standard commands as they like. +Also, different PMBUs devices act differently if non-supported commands are +executed. Some devices return an error, some devices return 0xff or 0xffff and +set a status error flag, and some devices may simply hang up. + +Despite all those difficulties, a generic PMBus device driver is still useful +and supported since kernel version 2.6.39. However, it was necessary to support +device specific extensions in addition to the core PMBus driver, since it is +simply unknown what new device specific functionality PMBus device developers +come up with next. + +To make device specific extensions as scalable as possible, and to avoid having +to modify the core PMBus driver repeatedly for new devices, the PMBus driver was +split into core, generic, and device specific code. The core code (in +pmbus_core.c) provides generic functionality. The generic code (in pmbus.c) +provides support for generic PMBus devices. Device specific code is responsible +for device specific initialization and, if needed, maps device specific +functionality into generic functionality. This is to some degree comparable +to PCI code, where generic code is augmented as needed with quirks for all kinds +of devices. + +PMBus device capabilities auto-detection +======================================== + +For generic PMBus devices, code in pmbus.c attempts to auto-detect all supported +PMBus commands. Auto-detection is somewhat limited, since there are simply too +many variables to consider. For example, it is almost impossible to autodetect +which PMBus commands are paged and which commands are replicated across all +pages (see the PMBus specification for details on multi-page PMBus devices). + +For this reason, it often makes sense to provide a device specific driver if not +all commands can be auto-detected. The data structures in this driver can be +used to inform the core driver about functionality supported by individual +chips. + +Some commands are always auto-detected. This applies to all limit commands +(lcrit, min, max, and crit attributes) as well as associated alarm attributes. +Limits and alarm attributes are auto-detected because there are simply too many +possible combinations to provide a manual configuration interface. + +PMBus internal API +================== + +The API between core and device specific PMBus code is defined in +drivers/hwmon/pmbus/pmbus.h. In addition to the internal API, pmbus.h defines +standard PMBus commands and virtual PMBus commands. + +Standard PMBus commands +----------------------- + +Standard PMBus commands (commands values 0x00 to 0xff) are defined in the PMBUs +specification. + +Virtual PMBus commands +---------------------- + +Virtual PMBus commands are provided to enable support for non-standard +functionality which has been implemented by several chip vendors and is thus +desirable to support. + +Virtual PMBus commands start with command value 0x100 and can thus easily be +distinguished from standard PMBus commands (which can not have values larger +than 0xff). Support for virtual PMBus commands is device specific and thus has +to be implemented in device specific code. + +Virtual commands are named PMBUS_VIRT_xxx and start with PMBUS_VIRT_BASE. All +virtual commands are word sized. + +There are currently two types of virtual commands. + +- READ commands are read-only; writes are either ignored or return an error. +- RESET commands are read/write. Reading reset registers returns zero + (used for detection), writing any value causes the associated history to be + reset. + +Virtual commands have to be handled in device specific driver code. Chip driver +code returns non-negative values if a virtual command is supported, or a +negative error code if not. The chip driver may return -ENODATA or any other +Linux error code in this case, though an error code other than -ENODATA is +handled more efficiently and thus preferred. Either case, the calling PMBus +core code will abort if the chip driver returns an error code when reading +or writing virtual registers (in other words, the PMBus core code will never +send a virtual command to a chip). + +PMBus driver information +------------------------ + +PMBus driver information, defined in struct pmbus_driver_info, is the main means +for device specific drivers to pass information to the core PMBus driver. +Specifically, it provides the following information. + +- For devices supporting its data in Direct Data Format, it provides coefficients + for converting register values into normalized data. This data is usually + provided by chip manufacturers in device datasheets. +- Supported chip functionality can be provided to the core driver. This may be + necessary for chips which react badly if non-supported commands are executed, + and/or to speed up device detection and initialization. +- Several function entry points are provided to support overriding and/or + augmenting generic command execution. This functionality can be used to map + non-standard PMBus commands to standard commands, or to augment standard + command return values with device specific information. + + API functions + ------------- + + Functions provided by chip driver + --------------------------------- + + All functions return the command return value (read) or zero (write) if + successful. A return value of -ENODATA indicates that there is no manufacturer + specific command, but that a standard PMBus command may exist. Any other + negative return value indicates that the commands does not exist for this + chip, and that no attempt should be made to read or write the standard + command. + + As mentioned above, an exception to this rule applies to virtual commands, + which _must_ be handled in driver specific code. See "Virtual PMBus Commands" + above for more details. + + Command execution in the core PMBus driver code is as follows. + + if (chip_access_function) { + status = chip_access_function(); + if (status != -ENODATA) + return status; + } + if (command >= PMBUS_VIRT_BASE) /* For word commands/registers only */ + return -EINVAL; + return generic_access(); + + Chip drivers may provide pointers to the following functions in struct + pmbus_driver_info. All functions are optional. + + int (*read_byte_data)(struct i2c_client *client, int page, int reg); + + Read byte from page , register . + may be -1, which means "current page". + + int (*read_word_data)(struct i2c_client *client, int page, int reg); + + Read word from page , register . + + int (*write_word_data)(struct i2c_client *client, int page, int reg, + u16 word); + + Write word to page , register . + + int (*write_byte)(struct i2c_client *client, int page, u8 value); + + Write byte to page , register . + may be -1, which means "current page". + + int (*identify)(struct i2c_client *client, struct pmbus_driver_info *info); + + Determine supported PMBus functionality. This function is only necessary + if a chip driver supports multiple chips, and the chip functionality is not + pre-determined. It is currently only used by the generic pmbus driver + (pmbus.c). + + Functions exported by core driver + --------------------------------- + + Chip drivers are expected to use the following functions to read or write + PMBus registers. Chip drivers may also use direct I2C commands. If direct I2C + commands are used, the chip driver code must not directly modify the current + page, since the selected page is cached in the core driver and the core driver + will assume that it is selected. Using pmbus_set_page() to select a new page + is mandatory. + + int pmbus_set_page(struct i2c_client *client, u8 page); + + Set PMBus page register to for subsequent commands. + + int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg); + + Read word data from , . Similar to i2c_smbus_read_word_data(), but + selects page first. + + int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, + u16 word); + + Write word data to , . Similar to i2c_smbus_write_word_data(), but + selects page first. + + int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg); + + Read byte data from , . Similar to i2c_smbus_read_byte_data(), but + selects page first. may be -1, which means "current page". + + int pmbus_write_byte(struct i2c_client *client, int page, u8 value); + + Write byte data to , . Similar to i2c_smbus_write_byte(), but + selects page first. may be -1, which means "current page". + + void pmbus_clear_faults(struct i2c_client *client); + + Execute PMBus "Clear Fault" command on all chip pages. + This function calls the device specific write_byte function if defined. + Therefore, it must _not_ be called from that function. + + bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg); + + Check if byte register exists. Return true if the register exists, false + otherwise. + This function calls the device specific write_byte function if defined to + obtain the chip status. Therefore, it must _not_ be called from that function. + + bool pmbus_check_word_register(struct i2c_client *client, int page, int reg); + + Check if word register exists. Return true if the register exists, false + otherwise. + This function calls the device specific write_byte function if defined to + obtain the chip status. Therefore, it must _not_ be called from that function. + + int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, + struct pmbus_driver_info *info); + + Execute probe function. Similar to standard probe function for other drivers, + with the pointer to struct pmbus_driver_info as additional argument. Calls + identify function if supported. Must only be called from device probe + function. + + void pmbus_do_remove(struct i2c_client *client); + + Execute driver remove function. Similar to standard driver remove function. + + const struct pmbus_driver_info + *pmbus_get_driver_info(struct i2c_client *client); + + Return pointer to struct pmbus_driver_info as passed to pmbus_do_probe(). + + +PMBus driver platform data +========================== + +PMBus platform data is defined in include/linux/i2c/pmbus.h. Platform data +currently only provides a flag field with a single bit used. + +#define PMBUS_SKIP_STATUS_CHECK (1 << 0) + +struct pmbus_platform_data { + u32 flags; /* Device specific flags */ +}; + + +Flags +----- + +PMBUS_SKIP_STATUS_CHECK + +During register detection, skip checking the status register for +communication or command errors. + +Some PMBus chips respond with valid data when trying to read an unsupported +register. For such chips, checking the status register is mandatory when +trying to determine if a chip register exists or not. +Other PMBus chips don't support the STATUS_CML register, or report +communication errors for no explicable reason. For such chips, checking the +status register must be disabled. + +Some i2c controllers do not support single-byte commands (write commands with +no data, i2c_smbus_write_byte()). With such controllers, clearing the status +register is impossible, and the PMBUS_SKIP_STATUS_CHECK flag must be set. diff --git a/Documentation/hwmon/zl6100 b/Documentation/hwmon/zl6100 new file mode 100644 index 0000000000000000000000000000000000000000..7617798b5c9736f49f8a69065739de9cb8267bbc --- /dev/null +++ b/Documentation/hwmon/zl6100 @@ -0,0 +1,125 @@ +Kernel driver zl6100 +==================== + +Supported chips: + * Intersil / Zilker Labs ZL2004 + Prefix: 'zl2004' + Addresses scanned: - + Datasheet: http://www.intersil.com/data/fn/fn6847.pdf + * Intersil / Zilker Labs ZL2006 + Prefix: 'zl2006' + Addresses scanned: - + Datasheet: http://www.intersil.com/data/fn/fn6850.pdf + * Intersil / Zilker Labs ZL2008 + Prefix: 'zl2008' + Addresses scanned: - + Datasheet: http://www.intersil.com/data/fn/fn6859.pdf + * Intersil / Zilker Labs ZL2105 + Prefix: 'zl2105' + Addresses scanned: - + Datasheet: http://www.intersil.com/data/fn/fn6851.pdf + * Intersil / Zilker Labs ZL2106 + Prefix: 'zl2106' + Addresses scanned: - + Datasheet: http://www.intersil.com/data/fn/fn6852.pdf + * Intersil / Zilker Labs ZL6100 + Prefix: 'zl6100' + Addresses scanned: - + Datasheet: http://www.intersil.com/data/fn/fn6876.pdf + * Intersil / Zilker Labs ZL6105 + Prefix: 'zl6105' + Addresses scanned: - + Datasheet: http://www.intersil.com/data/fn/fn6906.pdf + +Author: Guenter Roeck + + +Description +----------- + +This driver supports hardware montoring for Intersil / Zilker Labs ZL6100 and +compatible digital DC-DC controllers. + +The driver is a client driver to the core PMBus driver. Please see +Documentation/hwmon/pmbus and Documentation.hwmon/pmbus-core for details +on PMBus client drivers. + + +Usage Notes +----------- + +This driver does not auto-detect devices. You will have to instantiate the +devices explicitly. Please see Documentation/i2c/instantiating-devices for +details. + +WARNING: Do not access chip registers using the i2cdump command, and do not use +any of the i2ctools commands on a command register used to save and restore +configuration data (0x11, 0x12, 0x15, 0x16, and 0xf4). The chips supported by +this driver interpret any access to those command registers (including read +commands) as request to execute the command in question. Unless write accesses +to those registers are protected, this may result in power loss, board resets, +and/or Flash corruption. Worst case, your board may turn into a brick. + + +Platform data support +--------------------- + +The driver supports standard PMBus driver platform data. + + +Module parameters +----------------- + +delay +----- + +Some Intersil/Zilker Labs DC-DC controllers require a minimum interval between +I2C bus accesses. According to Intersil, the minimum interval is 2 ms, though +1 ms appears to be sufficient and has not caused any problems in testing. +The problem is known to affect ZL6100, ZL2105, and ZL2008. It is known not to +affect ZL2004 and ZL6105. The driver automatically sets the interval to 1 ms +except for ZL2004 and ZL6105. To enable manual override, the driver provides a +writeable module parameter, 'delay', which can be used to set the interval to +a value between 0 and 65,535 microseconds. + + +Sysfs entries +------------- + +The following attributes are supported. Limits are read-write; all other +attributes are read-only. + +in1_label "vin" +in1_input Measured input voltage. +in1_min Minimum input voltage. +in1_max Maximum input voltage. +in1_lcrit Critical minumum input voltage. +in1_crit Critical maximum input voltage. +in1_min_alarm Input voltage low alarm. +in1_max_alarm Input voltage high alarm. +in1_lcrit_alarm Input voltage critical low alarm. +in1_crit_alarm Input voltage critical high alarm. + +in2_label "vout1" +in2_input Measured output voltage. +in2_lcrit Critical minumum output Voltage. +in2_crit Critical maximum output voltage. +in2_lcrit_alarm Critical output voltage critical low alarm. +in2_crit_alarm Critical output voltage critical high alarm. + +curr1_label "iout1" +curr1_input Measured output current. +curr1_lcrit Critical minimum output current. +curr1_crit Critical maximum output current. +curr1_lcrit_alarm Output current critical low alarm. +curr1_crit_alarm Output current critical high alarm. + +temp[12]_input Measured temperature. +temp[12]_min Minimum temperature. +temp[12]_max Maximum temperature. +temp[12]_lcrit Critical low temperature. +temp[12]_crit Critical high temperature. +temp[12]_min_alarm Chip temperature low alarm. +temp[12]_max_alarm Chip temperature high alarm. +temp[12]_lcrit_alarm Chip temperature critical low alarm. +temp[12]_crit_alarm Chip temperature critical high alarm. diff --git a/Documentation/i2c/smbus-protocol b/Documentation/i2c/smbus-protocol index 7c19d1a2bea0a4936a20bfaad6972800c8bf4794..49f5b680809d9bfa3a97973aae095bf601d3cfcc 100644 --- a/Documentation/i2c/smbus-protocol +++ b/Documentation/i2c/smbus-protocol @@ -88,6 +88,10 @@ byte. But this time, the data is a complete word (16 bits). S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P +Note the convenience function i2c_smbus_read_word_swapped is +available for reads where the two data bytes are the other way +around (not SMBus compliant, but very popular.) + SMBus Write Byte: i2c_smbus_write_byte_data() ============================================== @@ -108,6 +112,10 @@ specified through the Comm byte. S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] P +Note the convenience function i2c_smbus_write_word_swapped is +available for writes where the two data bytes are the other way +around (not SMBus compliant, but very popular.) + SMBus Process Call: i2c_smbus_process_call() ============================================= diff --git a/Documentation/input/elantech.txt b/Documentation/input/elantech.txt index db798af5ef98a434cbb8c8828857627953c932ec..5602eb71ad5d7318e50952846d4f82edd3dcc239 100644 --- a/Documentation/input/elantech.txt +++ b/Documentation/input/elantech.txt @@ -16,15 +16,28 @@ Contents 1. Introduction 2. Extra knobs - 3. Hardware version 1 - 3.1 Registers - 3.2 Native relative mode 4 byte packet format - 3.3 Native absolute mode 4 byte packet format - 4. Hardware version 2 + 3. Differentiating hardware versions + 4. Hardware version 1 4.1 Registers - 4.2 Native absolute mode 6 byte packet format - 4.2.1 One finger touch - 4.2.2 Two finger touch + 4.2 Native relative mode 4 byte packet format + 4.3 Native absolute mode 4 byte packet format + 5. Hardware version 2 + 5.1 Registers + 5.2 Native absolute mode 6 byte packet format + 5.2.1 Parity checking and packet re-synchronization + 5.2.2 One/Three finger touch + 5.2.3 Two finger touch + 6. Hardware version 3 + 6.1 Registers + 6.2 Native absolute mode 6 byte packet format + 6.2.1 One/Three finger touch + 6.2.2 Two finger touch + 7. Hardware version 4 + 7.1 Registers + 7.2 Native absolute mode 6 byte packet format + 7.2.1 Status packet + 7.2.2 Head packet + 7.2.3 Motion packet @@ -375,7 +388,7 @@ For all the other ones, there are just a few constant bits: In case an error is detected, all the packets are shifted by one (and packet[0] is discarded). -5.2.1 One/Three finger touch +5.2.2 One/Three finger touch ~~~~~~~~~~~~~~~~ byte 0: @@ -384,19 +397,19 @@ byte 0: n1 n0 w3 w2 . . R L L, R = 1 when Left, Right mouse button pressed - n1..n0 = numbers of fingers on touchpad + n1..n0 = number of fingers on touchpad byte 1: bit 7 6 5 4 3 2 1 0 - p7 p6 p5 p4 . x10 x9 x8 + p7 p6 p5 p4 x11 x10 x9 x8 byte 2: bit 7 6 5 4 3 2 1 0 x7 x6 x5 x4 x3 x2 x1 x0 - x10..x0 = absolute x value (horizontal) + x11..x0 = absolute x value (horizontal) byte 3: @@ -420,7 +433,7 @@ byte 3: byte 4: bit 7 6 5 4 3 2 1 0 - p3 p1 p2 p0 . . y9 y8 + p3 p1 p2 p0 y11 y10 y9 y8 p7..p0 = pressure (not EF113) @@ -429,10 +442,10 @@ byte 5: bit 7 6 5 4 3 2 1 0 y7 y6 y5 y4 y3 y2 y1 y0 - y9..y0 = absolute y value (vertical) + y11..y0 = absolute y value (vertical) -4.2.2 Two finger touch +5.2.3 Two finger touch ~~~~~~~~~~~~~~~~ Note that the two pairs of coordinates are not exactly the coordinates of the @@ -446,7 +459,7 @@ byte 0: n1 n0 ay8 ax8 . . R L L, R = 1 when Left, Right mouse button pressed - n1..n0 = numbers of fingers on touchpad + n1..n0 = number of fingers on touchpad byte 1: @@ -480,3 +493,253 @@ byte 5: by7 by8 by5 by4 by3 by2 by1 by0 by8..by0 = upper-right finger absolute y value + +///////////////////////////////////////////////////////////////////////////// + +6. Hardware version 3 + ================== + +6.1 Registers + ~~~~~~~~~ +* reg_10 + + bit 7 6 5 4 3 2 1 0 + 0 0 0 0 0 0 0 A + + A: 1 = enable absolute tracking + +6.2 Native absolute mode 6 byte packet format + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +1 and 3 finger touch shares the same 6-byte packet format, except that +3 finger touch only reports the position of the center of all three fingers. + +Firmware would send 12 bytes of data for 2 finger touch. + +Note on debounce: +In case the box has unstable power supply or other electricity issues, or +when number of finger changes, F/W would send "debounce packet" to inform +driver that the hardware is in debounce status. +The debouce packet has the following signature: + byte 0: 0xc4 + byte 1: 0xff + byte 2: 0xff + byte 3: 0x02 + byte 4: 0xff + byte 5: 0xff +When we encounter this kind of packet, we just ignore it. + +6.2.1 One/Three finger touch + ~~~~~~~~~~~~~~~~~~~~~~ + +byte 0: + + bit 7 6 5 4 3 2 1 0 + n1 n0 w3 w2 0 1 R L + + L, R = 1 when Left, Right mouse button pressed + n1..n0 = number of fingers on touchpad + +byte 1: + + bit 7 6 5 4 3 2 1 0 + p7 p6 p5 p4 x11 x10 x9 x8 + +byte 2: + + bit 7 6 5 4 3 2 1 0 + x7 x6 x5 x4 x3 x2 x1 x0 + + x11..x0 = absolute x value (horizontal) + +byte 3: + + bit 7 6 5 4 3 2 1 0 + 0 0 w1 w0 0 0 1 0 + + w3..w0 = width of the finger touch + +byte 4: + + bit 7 6 5 4 3 2 1 0 + p3 p1 p2 p0 y11 y10 y9 y8 + + p7..p0 = pressure + +byte 5: + + bit 7 6 5 4 3 2 1 0 + y7 y6 y5 y4 y3 y2 y1 y0 + + y11..y0 = absolute y value (vertical) + +6.2.2 Two finger touch + ~~~~~~~~~~~~~~~~ + +The packet format is exactly the same for two finger touch, except the hardware +sends two 6 byte packets. The first packet contains data for the first finger, +the second packet has data for the second finger. So for two finger touch a +total of 12 bytes are sent. + +///////////////////////////////////////////////////////////////////////////// + +7. Hardware version 4 + ================== + +7.1 Registers + ~~~~~~~~~ +* reg_07 + + bit 7 6 5 4 3 2 1 0 + 0 0 0 0 0 0 0 A + + A: 1 = enable absolute tracking + +7.2 Native absolute mode 6 byte packet format + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +v4 hardware is a true multitouch touchpad, capable of tracking up to 5 fingers. +Unfortunately, due to PS/2's limited bandwidth, its packet format is rather +complex. + +Whenever the numbers or identities of the fingers changes, the hardware sends a +status packet to indicate how many and which fingers is on touchpad, followed by +head packets or motion packets. A head packet contains data of finger id, finger +position (absolute x, y values), width, and pressure. A motion packet contains +two fingers' position delta. + +For example, when status packet tells there are 2 fingers on touchpad, then we +can expect two following head packets. If the finger status doesn't change, +the following packets would be motion packets, only sending delta of finger +position, until we receive a status packet. + +One exception is one finger touch. when a status packet tells us there is only +one finger, the hardware would just send head packets afterwards. + +7.2.1 Status packet + ~~~~~~~~~~~~~ + +byte 0: + + bit 7 6 5 4 3 2 1 0 + . . . . 0 1 R L + + L, R = 1 when Left, Right mouse button pressed + +byte 1: + + bit 7 6 5 4 3 2 1 0 + . . . ft4 ft3 ft2 ft1 ft0 + + ft4 ft3 ft2 ft1 ft0 ftn = 1 when finger n is on touchpad + +byte 2: not used + +byte 3: + + bit 7 6 5 4 3 2 1 0 + . . . 1 0 0 0 0 + + constant bits + +byte 4: + + bit 7 6 5 4 3 2 1 0 + p . . . . . . . + + p = 1 for palm + +byte 5: not used + +7.2.2 Head packet + ~~~~~~~~~~~ + +byte 0: + + bit 7 6 5 4 3 2 1 0 + w3 w2 w1 w0 0 1 R L + + L, R = 1 when Left, Right mouse button pressed + w3..w0 = finger width (spans how many trace lines) + +byte 1: + + bit 7 6 5 4 3 2 1 0 + p7 p6 p5 p4 x11 x10 x9 x8 + +byte 2: + + bit 7 6 5 4 3 2 1 0 + x7 x6 x5 x4 x3 x2 x1 x0 + + x11..x0 = absolute x value (horizontal) + +byte 3: + + bit 7 6 5 4 3 2 1 0 + id2 id1 id0 1 0 0 0 1 + + id2..id0 = finger id + +byte 4: + + bit 7 6 5 4 3 2 1 0 + p3 p1 p2 p0 y11 y10 y9 y8 + + p7..p0 = pressure + +byte 5: + + bit 7 6 5 4 3 2 1 0 + y7 y6 y5 y4 y3 y2 y1 y0 + + y11..y0 = absolute y value (vertical) + +7.2.3 Motion packet + ~~~~~~~~~~~~~ + +byte 0: + + bit 7 6 5 4 3 2 1 0 + id2 id1 id0 w 0 1 R L + + L, R = 1 when Left, Right mouse button pressed + id2..id0 = finger id + w = 1 when delta overflows (> 127 or < -128), in this case + firmware sends us (delta x / 5) and (delta y / 5) + +byte 1: + + bit 7 6 5 4 3 2 1 0 + x7 x6 x5 x4 x3 x2 x1 x0 + + x7..x0 = delta x (two's complement) + +byte 2: + + bit 7 6 5 4 3 2 1 0 + y7 y6 y5 y4 y3 y2 y1 y0 + + y7..y0 = delta y (two's complement) + +byte 3: + + bit 7 6 5 4 3 2 1 0 + id2 id1 id0 1 0 0 1 0 + + id2..id0 = finger id + +byte 4: + + bit 7 6 5 4 3 2 1 0 + x7 x6 x5 x4 x3 x2 x1 x0 + + x7..x0 = delta x (two's complement) + +byte 5: + + bit 7 6 5 4 3 2 1 0 + y7 y6 y5 y4 y3 y2 y1 y0 + + y7..y0 = delta y (two's complement) + + byte 0 ~ 2 for one finger + byte 3 ~ 5 for another diff --git a/Documentation/input/input.txt b/Documentation/input/input.txt index b93c08442e3c773bcfb0a887e7f849694ea4b9b3..b3d6787b4fb11b0c55c562ef1c8f80d1e6f13668 100644 --- a/Documentation/input/input.txt +++ b/Documentation/input/input.txt @@ -111,7 +111,7 @@ LCDs and many other purposes. The monitor and speaker controls should be easy to add to the hid/input interface, but for the UPSs and LCDs it doesn't make much sense. For this, -the hiddev interface was designed. See Documentation/usb/hiddev.txt +the hiddev interface was designed. See Documentation/hid/hiddev.txt for more information about it. The usage of the usbhid module is very simple, it takes no parameters, diff --git a/Documentation/input/multi-touch-protocol.txt b/Documentation/input/multi-touch-protocol.txt index 71536e78406f06a305f8d930535832be3c435dee..543101c5bf260e550a9fa07b38be764294ca4eca 100644 --- a/Documentation/input/multi-touch-protocol.txt +++ b/Documentation/input/multi-touch-protocol.txt @@ -65,6 +65,20 @@ the full state of each initiated contact has to reside in the receiving end. Upon receiving an MT event, one simply updates the appropriate attribute of the current slot. +Some devices identify and/or track more contacts than they can report to the +driver. A driver for such a device should associate one type B slot with each +contact that is reported by the hardware. Whenever the identity of the +contact associated with a slot changes, the driver should invalidate that +slot by changing its ABS_MT_TRACKING_ID. If the hardware signals that it is +tracking more contacts than it is currently reporting, the driver should use +a BTN_TOOL_*TAP event to inform userspace of the total number of contacts +being tracked by the hardware at that moment. The driver should do this by +explicitly sending the corresponding BTN_TOOL_*TAP event and setting +use_count to false when calling input_mt_report_pointer_emulation(). +The driver should only advertise as many slots as the hardware can report. +Userspace can detect that a driver can report more total contacts than slots +by noting that the largest supported BTN_TOOL_*TAP event is larger than the +total number of type B slots reported in the absinfo for the ABS_MT_SLOT axis. Protocol Example A ------------------ diff --git a/Documentation/kernel-docs.txt b/Documentation/kernel-docs.txt index 0e0734b509d84097f1ed02e653cf0f4bfbadc6c0..eda1eb1451a0881097bfaa8ad76c18acd6945f36 100644 --- a/Documentation/kernel-docs.txt +++ b/Documentation/kernel-docs.txt @@ -300,7 +300,7 @@ * Title: "The Kernel Hacking HOWTO" Author: Various Talented People, and Rusty. - Location: in kernel tree, Documentation/DocBook/kernel-hacking/ + Location: in kernel tree, Documentation/DocBook/kernel-hacking.tmpl (must be built as "make {htmldocs | psdocs | pdfdocs}) Keywords: HOWTO, kernel contexts, deadlock, locking, modules, symbols, return conventions. @@ -351,7 +351,7 @@ * Title: "Linux Kernel Locking HOWTO" Author: Various Talented People, and Rusty. - Location: in kernel tree, Documentation/DocBook/kernel-locking/ + Location: in kernel tree, Documentation/DocBook/kernel-locking.tmpl (must be built as "make {htmldocs | psdocs | pdfdocs}) Keywords: locks, locking, spinlock, semaphore, atomic, race condition, bottom halves, tasklets, softirqs. diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index d6e6724446c88722500a01db7f35d2a23ba7ac5f..a0c5c5f4fce6e9587346a4a049c9725e5ca45de5 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -49,6 +49,7 @@ parameter is applicable: EDD BIOS Enhanced Disk Drive Services (EDD) is enabled EFI EFI Partitioning (GPT) is enabled EIDE EIDE/ATAPI support is enabled. + EVM Extended Verification Module FB The frame buffer device is enabled. FTRACE Function tracing enabled. GCOV GCOV profiling is enabled. @@ -163,7 +164,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. rsdt -- prefer RSDT over (default) XSDT copy_dsdt -- copy DSDT to memory - See also Documentation/power/pm.txt, pci=noacpi + See also Documentation/power/runtime_pm.txt, pci=noacpi acpi_rsdp= [ACPI,EFI,KEXEC] Pass the RSDP address to the kernel, mostly used @@ -306,6 +307,19 @@ bytes respectively. Such letter suffixes can also be entirely omitted. behaviour to be specified. Bit 0 enables warnings, bit 1 enables fixups, and bit 2 sends a segfault. + align_va_addr= [X86-64] + Align virtual addresses by clearing slice [14:12] when + allocating a VMA at process creation time. This option + gives you up to 3% performance improvement on AMD F15h + machines (where it is enabled by default) for a + CPU-intensive style benchmark, and it can vary highly in + a microbenchmark depending on workload and compiler. + + 1: only for 32-bit processes + 2: only for 64-bit processes + on: enable for both 32- and 64-bit processes + off: disable for both 32- and 64-bit processes + amd_iommu= [HW,X86-84] Pass parameters to the AMD IOMMU driver in the system. Possible values are: @@ -319,7 +333,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. amijoy.map= [HW,JOY] Amiga joystick support Map of devices attached to JOY0DAT and JOY1DAT Format: , - See also Documentation/kernel/input/joystick.txt + See also Documentation/input/joystick.txt analog.map= [HW,JOY] Analog joystick and gamepad support Specifies type or capabilities of an analog joystick @@ -408,7 +422,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. bttv.radio= Most important insmod options are available as kernel args too. bttv.pll= See Documentation/video4linux/bttv/Insmod-options - bttv.tuner= and Documentation/video4linux/bttv/CARDLIST + bttv.tuner= bulk_remove=off [PPC] This parameter disables the use of the pSeries firmware feature for flushing multiple hpte entries @@ -724,13 +738,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. elevator= [IOSCHED] Format: {"cfq" | "deadline" | "noop"} - See Documentation/block/as-iosched.txt and + See Documentation/block/cfq-iosched.txt and Documentation/block/deadline-iosched.txt for details. - elfcorehdr= [IA-64,PPC,SH,X86] + elfcorehdr=[size[KMG]@]offset[KMG] [IA64,PPC,SH,X86,S390] Specifies physical address of start of kernel core - image elf header. Generally kexec loader will - pass this option to capture kernel. + image elf header and optionally the size. Generally + kexec loader will pass this option to capture kernel. See Documentation/kdump/kdump.txt for details. enable_mtrr_cleanup [X86] @@ -760,12 +774,17 @@ bytes respectively. Such letter suffixes can also be entirely omitted. This option is obsoleted by the "netdev=" option, which has equivalent usage. See its documentation for details. + evm= [EVM] + Format: { "fix" } + Permit 'security.evm' to be updated regardless of + current integrity status. + failslab= fail_page_alloc= fail_make_request=[KNL] General fault injection mechanism. Format: ,,, - See also /Documentation/fault-injection/. + See also Documentation/fault-injection/. floppy= [HW] See Documentation/blockdev/floppy.txt. @@ -954,6 +973,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted. ignore_loglevel [KNL] Ignore loglevel setting - this will print /all/ kernel messages to the console. Useful for debugging. + We also add it as printk module parameter, so users + could change it dynamically, usually by + /sys/module/printk/parameters/ignore_loglevel. ihash_entries= [KNL] Set number of hash buckets for inode cache. @@ -1014,10 +1036,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted. has the capability. With this option, super page will not be supported. intremap= [X86-64, Intel-IOMMU] - Format: { on (default) | off | nosid } on enable Interrupt Remapping (default) off disable Interrupt Remapping nosid disable Source ID checking + no_x2apic_optout + BIOS x2APIC opt-out request will be ignored inttest= [IA-64] @@ -1181,6 +1204,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted. [KVM,Intel] Disable FlexPriority feature (TPR shadow). Default is 1 (enabled) + kvm-intel.nested= + [KVM,Intel] Enable VMX nesting (nVMX). + Default is 0 (disabled) + kvm-intel.unrestricted_guest= [KVM,Intel] Disable unrestricted guest feature (virtualized real and unpaged mode) on capable @@ -1642,6 +1669,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted. debugging driver suspend/resume hooks). This may not work reliably with all consoles, but is known to work with serial and VGA consoles. + To facilitate more flexible debugging, we also add + console_suspend, a printk module parameter to control + it. Users could use console_suspend (usually + /sys/module/printk/parameters/console_suspend) to + turn on/off it dynamically. noaliencache [MM, NUMA, SLAB] Disables the allocation of alien caches in the slab allocator. Saves per-node memory, @@ -1777,6 +1809,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted. noresidual [PPC] Don't use residual data on PReP machines. + nordrand [X86] Disable the direct use of the RDRAND + instruction even if it is supported by the + processor. RDRAND is still available to user + space applications. + noresume [SWSUSP] Disables resume and restores original swap space. @@ -2240,6 +2277,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. in units (needed only for swap files). See Documentation/power/swsusp-and-swap-files.txt + resumedelay= [HIBERNATION] Delay (in seconds) to pause before attempting to + read the resume files + + resumewait [HIBERNATION] Wait (indefinitely) for resume device to show up. + Useful for devices that are detected asynchronously + (e.g. USB and MMC devices). + hibernate= [HIBERNATION] noresume Don't check if there's a hibernation image present during boot. @@ -2375,7 +2419,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. Format: sonypi.*= [HW] Sony Programmable I/O Control Device driver - See Documentation/sonypi.txt + See Documentation/laptops/sonypi.txt specialix= [HW,SERIAL] Specialix multi-serial port adapter See Documentation/serial/specialix.txt. diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index 61815483efa34d9f7118d4aa91b321c66d42db44..3ff0dad62d36df880ee27ec2f32a27644379a21d 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt @@ -736,7 +736,7 @@ status as "unknown". The available commands are: sysfs notes: The ThinkLight sysfs interface is documented by the LED class -documentation, in Documentation/leds-class.txt. The ThinkLight LED name +documentation, in Documentation/leds/leds-class.txt. The ThinkLight LED name is "tpacpi::thinklight". Due to limitations in the sysfs LED class, if the status of the ThinkLight @@ -833,7 +833,7 @@ All of the above can be turned on and off and can be made to blink. sysfs notes: The ThinkPad LED sysfs interface is described in detail by the LED class -documentation, in Documentation/leds-class.txt. +documentation, in Documentation/leds/leds-class.txt. The LEDs are named (in LED ID order, from 0 to 12): "tpacpi::power", "tpacpi:orange:batt", "tpacpi:green:batt", diff --git a/Documentation/media-framework.txt b/Documentation/media-framework.txt index 669b5fb03a868c32f2a3e36fc2380727b66d1636..3a0f879533ce1659c137be6769434420f9f3d2d9 100644 --- a/Documentation/media-framework.txt +++ b/Documentation/media-framework.txt @@ -9,8 +9,8 @@ Introduction ------------ The media controller API is documented in DocBook format in -Documentation/DocBook/v4l/media-controller.xml. This document will focus on -the kernel-side implementation of the media framework. +Documentation/DocBook/media/v4l/media-controller.xml. This document will focus +on the kernel-side implementation of the media framework. Abstract media device model diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt index f0d3a8026a5628fa130a525a18a9b58157a7edb0..2759f7c188f0cd9232ce10122d3dd6595b4f0d30 100644 --- a/Documentation/memory-barriers.txt +++ b/Documentation/memory-barriers.txt @@ -438,7 +438,7 @@ There are certain things that the Linux kernel memory barriers do not guarantee: [*] For information on bus mastering DMA and coherency please read: Documentation/PCI/pci.txt - Documentation/PCI/PCI-DMA-mapping.txt + Documentation/DMA-API-HOWTO.txt Documentation/DMA-API.txt diff --git a/Documentation/networking/LICENSE.qlcnic b/Documentation/networking/LICENSE.qlcnic index 29ad4b1064206ef8e4634470f45b9671a7d1cca9..e7fb2c6023bc896dec6dd348961dce06a7bff217 100644 --- a/Documentation/networking/LICENSE.qlcnic +++ b/Documentation/networking/LICENSE.qlcnic @@ -1,61 +1,22 @@ -Copyright (c) 2009-2010 QLogic Corporation +Copyright (c) 2009-2011 QLogic Corporation QLogic Linux qlcnic NIC Driver -This program includes a device driver for Linux 2.6 that may be -distributed with QLogic hardware specific firmware binary file. You may modify and redistribute the device driver code under the GNU General Public License (a copy of which is attached hereto as Exhibit A) published by the Free Software Foundation (version 2). -You may redistribute the hardware specific firmware binary file -under the following terms: - - 1. Redistribution of source code (only if applicable), - must retain the above copyright notice, this list of - conditions and the following disclaimer. - - 2. Redistribution 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. - - 3. The name of QLogic Corporation may not be used to - endorse or promote products derived from this software - without specific prior written permission - -REGARDLESS OF WHAT LICENSING MECHANISM IS USED OR APPLICABLE, -THIS PROGRAM IS PROVIDED BY QLOGIC CORPORATION "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 AUTHOR -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 -POSSIBILITY OF SUCH DAMAGE. - -USER ACKNOWLEDGES AND AGREES THAT USE OF THIS PROGRAM WILL NOT -CREATE OR GIVE GROUNDS FOR A LICENSE BY IMPLICATION, ESTOPPEL, OR -OTHERWISE IN ANY INTELLECTUAL PROPERTY RIGHTS (PATENT, COPYRIGHT, -TRADE SECRET, MASK WORK, OR OTHER PROPRIETARY RIGHT) EMBODIED IN -ANY OTHER QLOGIC HARDWARE OR SOFTWARE EITHER SOLELY OR IN -COMBINATION WITH THIS PROGRAM. - EXHIBIT A - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. - Preamble + Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public @@ -105,7 +66,7 @@ patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. - GNU GENERAL PUBLIC LICENSE + GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains @@ -304,7 +265,7 @@ make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. - NO WARRANTY + NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN diff --git a/Documentation/networking/batman-adv.txt b/Documentation/networking/batman-adv.txt index 88d4afbdef98a913b539e3973a804220f491635c..c86d03f18a5be6c70c97f2fadacd0cb93f66f800 100644 --- a/Documentation/networking/batman-adv.txt +++ b/Documentation/networking/batman-adv.txt @@ -1,4 +1,4 @@ -[state: 17-04-2011] +[state: 21-08-2011] BATMAN-ADV ---------- @@ -68,9 +68,9 @@ All mesh wide settings can be found in batman's own interface folder: # ls /sys/class/net/bat0/mesh/ -# aggregated_ogms gw_bandwidth hop_penalty -# bonding gw_mode orig_interval -# fragmentation gw_sel_class vis_mode +# aggregated_ogms fragmentation gw_sel_class vis_mode +# ap_isolation gw_bandwidth hop_penalty +# bonding gw_mode orig_interval There is a special folder for debugging information: diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index ca5cdcd0f0e3688364f7097d0201f2b4079d5c42..cb7f3148035dbeaabbcc514ddf53705733321d66 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -1045,6 +1045,11 @@ conf/interface/*: accept_ra - INTEGER Accept Router Advertisements; autoconfigure using them. + It also determines whether or not to transmit Router + Solicitations. If and only if the functional setting is to + accept Router Advertisements, Router Solicitations will be + transmitted. + Possible values are: 0 Do not accept Router Advertisements. 1 Accept Router Advertisements if forwarding is disabled. @@ -1115,14 +1120,14 @@ forwarding - INTEGER Possible values are: 0 Forwarding disabled 1 Forwarding enabled - 2 Forwarding enabled (Hybrid Mode) FALSE (0): By default, Host behaviour is assumed. This means: 1. IsRouter flag is not set in Neighbour Advertisements. - 2. Router Solicitations are being sent when necessary. + 2. If accept_ra is TRUE (default), transmit Router + Solicitations. 3. If accept_ra is TRUE (default), accept Router Advertisements (and do autoconfiguration). 4. If accept_redirects is TRUE (default), accept Redirects. @@ -1133,16 +1138,10 @@ forwarding - INTEGER This means exactly the reverse from the above: 1. IsRouter flag is set in Neighbour Advertisements. - 2. Router Solicitations are not sent. + 2. Router Solicitations are not sent unless accept_ra is 2. 3. Router Advertisements are ignored unless accept_ra is 2. 4. Redirects are ignored. - TRUE (2): - - Hybrid mode. Same behaviour as TRUE, except for: - - 2. Router Solicitations are being sent when necessary. - Default: 0 (disabled) if global forwarding is disabled (default), otherwise 1 (enabled). diff --git a/Documentation/networking/mac80211-injection.txt b/Documentation/networking/mac80211-injection.txt index b30e81ad5307e851c50d58386bb17eb68d2072c9..3a930072b161fd51b3b1d007daac673526609dc2 100644 --- a/Documentation/networking/mac80211-injection.txt +++ b/Documentation/networking/mac80211-injection.txt @@ -23,6 +23,10 @@ radiotap headers and used to control injection: IEEE80211_RADIOTAP_F_FRAG: frame will be fragmented if longer than the current fragmentation threshold. + * IEEE80211_RADIOTAP_TX_FLAGS + + IEEE80211_RADIOTAP_F_TX_NOACK: frame should be sent without waiting for + an ACK even if it is a unicast frame The injection code can also skip all other currently defined radiotap fields facilitating replay of captured radiotap headers directly. diff --git a/Documentation/networking/netdevices.txt b/Documentation/networking/netdevices.txt index 87b3d15f523ad49863d927801269efd1b5fb65de..89358341682a1290879d26b854c1527991b54768 100644 --- a/Documentation/networking/netdevices.txt +++ b/Documentation/networking/netdevices.txt @@ -73,7 +73,7 @@ dev->hard_start_xmit: has to lock by itself when needed. It is recommended to use a try lock for this and return NETDEV_TX_LOCKED when the spin lock fails. The locking there should also properly protect against - set_multicast_list. Note that the use of NETIF_F_LLTX is deprecated. + set_rx_mode. Note that the use of NETIF_F_LLTX is deprecated. Don't use it for new drivers. Context: Process with BHs disabled or BH (timer), @@ -92,7 +92,7 @@ dev->tx_timeout: Context: BHs disabled Notes: netif_queue_stopped() is guaranteed true -dev->set_multicast_list: +dev->set_rx_mode: Synchronization: netif_tx_lock spinlock. Context: BHs disabled diff --git a/Documentation/networking/scaling.txt b/Documentation/networking/scaling.txt index fe67b5c79f0ff33d92ebe7469a89c5a5d044fc0a..a177de21d28e5545bfc89b8569226295e1c80b34 100644 --- a/Documentation/networking/scaling.txt +++ b/Documentation/networking/scaling.txt @@ -73,7 +73,7 @@ of queues to IRQs can be determined from /proc/interrupts. By default, an IRQ may be handled on any CPU. Because a non-negligible part of packet processing takes place in receive interrupt handling, it is advantageous to spread receive interrupts between CPUs. To manually adjust the IRQ -affinity of each interrupt see Documentation/IRQ-affinity. Some systems +affinity of each interrupt see Documentation/IRQ-affinity.txt. Some systems will be running irqbalance, a daemon that dynamically optimizes IRQ assignments and as a result may override any manual settings. diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt index 57a24108b8455aa55b89030474bb0785e3573c1c..8d67980fabe8d2a23affc6513523046f70acad42 100644 --- a/Documentation/networking/stmmac.txt +++ b/Documentation/networking/stmmac.txt @@ -76,7 +76,16 @@ core. 4.5) DMA descriptors Driver handles both normal and enhanced descriptors. The latter has been only -tested on DWC Ether MAC 10/100/1000 Universal version 3.41a. +tested on DWC Ether MAC 10/100/1000 Universal version 3.41a and later. + +STMMAC supports DMA descriptor to operate both in dual buffer (RING) +and linked-list(CHAINED) mode. In RING each descriptor points to two +data buffer pointers whereas in CHAINED mode they point to only one data +buffer pointer. RING mode is the default. + +In CHAINED mode each descriptor will have pointer to next descriptor in +the list, hence creating the explicit chaining in the descriptor itself, +whereas such explicit chaining is not possible in RING mode. 4.6) Ethtool support Ethtool is supported. Driver statistics and internal errors can be taken using: @@ -235,7 +244,38 @@ reset procedure etc). o enh_desc.c: functions for handling enhanced descriptors o norm_desc.c: functions for handling normal descriptors -5) TODO: +5) Debug Information + +The driver exports many information i.e. internal statistics, +debug information, MAC and DMA registers etc. + +These can be read in several ways depending on the +type of the information actually needed. + +For example a user can be use the ethtool support +to get statistics: e.g. using: ethtool -S ethX +(that shows the Management counters (MMC) if supported) +or sees the MAC/DMA registers: e.g. using: ethtool -d ethX + +Compiling the Kernel with CONFIG_DEBUG_FS and enabling the +STMMAC_DEBUG_FS option the driver will export the following +debugfs entries: + +/sys/kernel/debug/stmmaceth/descriptors_status + To show the DMA TX/RX descriptor rings + +Developer can also use the "debug" module parameter to get +further debug information. + +In the end, there are other macros (that cannot be enabled +via menuconfig) to turn-on the RX/TX DMA debugging, +specific MAC core debug printk etc. Others to enable the +debug in the TX and RX processes. +All these are only useful during the developing stage +and should never enabled inside the code for general usage. +In fact, these can generate an huge amount of debug messages. + +6) TODO: o XGMAC is not supported. o Review the timer optimisation code to use an embedded device that will be available in new chip generations. diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt new file mode 100644 index 0000000000000000000000000000000000000000..b04cb7d45a1632625a194883587b1300690a200c --- /dev/null +++ b/Documentation/pinctrl.txt @@ -0,0 +1,950 @@ +PINCTRL (PIN CONTROL) subsystem +This document outlines the pin control subsystem in Linux + +This subsystem deals with: + +- Enumerating and naming controllable pins + +- Multiplexing of pins, pads, fingers (etc) see below for details + +The intention is to also deal with: + +- Software-controlled biasing and driving mode specific pins, such as + pull-up/down, open drain etc, load capacitance configuration when controlled + by software, etc. + + +Top-level interface +=================== + +Definition of PIN CONTROLLER: + +- A pin controller is a piece of hardware, usually a set of registers, that + can control PINs. It may be able to multiplex, bias, set load capacitance, + set drive strength etc for individual pins or groups of pins. + +Definition of PIN: + +- PINS are equal to pads, fingers, balls or whatever packaging input or + output line you want to control and these are denoted by unsigned integers + in the range 0..maxpin. This numberspace is local to each PIN CONTROLLER, so + there may be several such number spaces in a system. This pin space may + be sparse - i.e. there may be gaps in the space with numbers where no + pin exists. + +When a PIN CONTROLLER is instatiated, it will register a descriptor to the +pin control framework, and this descriptor contains an array of pin descriptors +describing the pins handled by this specific pin controller. + +Here is an example of a PGA (Pin Grid Array) chip seen from underneath: + + A B C D E F G H + + 8 o o o o o o o o + + 7 o o o o o o o o + + 6 o o o o o o o o + + 5 o o o o o o o o + + 4 o o o o o o o o + + 3 o o o o o o o o + + 2 o o o o o o o o + + 1 o o o o o o o o + +To register a pin controller and name all the pins on this package we can do +this in our driver: + +#include + +const struct pinctrl_pin_desc __refdata foo_pins[] = { + PINCTRL_PIN(0, "A1"), + PINCTRL_PIN(1, "A2"), + PINCTRL_PIN(2, "A3"), + ... + PINCTRL_PIN(61, "H6"), + PINCTRL_PIN(62, "H7"), + PINCTRL_PIN(63, "H8"), +}; + +static struct pinctrl_desc foo_desc = { + .name = "foo", + .pins = foo_pins, + .npins = ARRAY_SIZE(foo_pins), + .maxpin = 63, + .owner = THIS_MODULE, +}; + +int __init foo_probe(void) +{ + struct pinctrl_dev *pctl; + + pctl = pinctrl_register(&foo_desc, , NULL); + if (IS_ERR(pctl)) + pr_err("could not register foo pin driver\n"); +} + +Pins usually have fancier names than this. You can find these in the dataheet +for your chip. Notice that the core pinctrl.h file provides a fancy macro +called PINCTRL_PIN() to create the struct entries. As you can see I enumerated +the pins from 0 in the upper left corner to 63 in the lower right corner, +this enumeration was arbitrarily chosen, in practice you need to think +through your numbering system so that it matches the layout of registers +and such things in your driver, or the code may become complicated. You must +also consider matching of offsets to the GPIO ranges that may be handled by +the pin controller. + +For a padring with 467 pads, as opposed to actual pins, I used an enumeration +like this, walking around the edge of the chip, which seems to be industry +standard too (all these pads had names, too): + + + 0 ..... 104 + 466 105 + . . + . . + 358 224 + 357 .... 225 + + +Pin groups +========== + +Many controllers need to deal with groups of pins, so the pin controller +subsystem has a mechanism for enumerating groups of pins and retrieving the +actual enumerated pins that are part of a certain group. + +For example, say that we have a group of pins dealing with an SPI interface +on { 0, 8, 16, 24 }, and a group of pins dealing with an I2C interface on pins +on { 24, 25 }. + +These two groups are presented to the pin control subsystem by implementing +some generic pinctrl_ops like this: + +#include + +struct foo_group { + const char *name; + const unsigned int *pins; + const unsigned num_pins; +}; + +static unsigned int spi0_pins[] = { 0, 8, 16, 24 }; +static unsigned int i2c0_pins[] = { 24, 25 }; + +static const struct foo_group foo_groups[] = { + { + .name = "spi0_grp", + .pins = spi0_pins, + .num_pins = ARRAY_SIZE(spi0_pins), + }, + { + .name = "i2c0_grp", + .pins = i2c0_pins, + .num_pins = ARRAY_SIZE(i2c0_pins), + }, +}; + + +static int foo_list_groups(struct pinctrl_dev *pctldev, unsigned selector) +{ + if (selector >= ARRAY_SIZE(foo_groups)) + return -EINVAL; + return 0; +} + +static const char *foo_get_group_name(struct pinctrl_dev *pctldev, + unsigned selector) +{ + return foo_groups[selector].name; +} + +static int foo_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector, + unsigned ** const pins, + unsigned * const num_pins) +{ + *pins = (unsigned *) foo_groups[selector].pins; + *num_pins = foo_groups[selector].num_pins; + return 0; +} + +static struct pinctrl_ops foo_pctrl_ops = { + .list_groups = foo_list_groups, + .get_group_name = foo_get_group_name, + .get_group_pins = foo_get_group_pins, +}; + + +static struct pinctrl_desc foo_desc = { + ... + .pctlops = &foo_pctrl_ops, +}; + +The pin control subsystem will call the .list_groups() function repeatedly +beginning on 0 until it returns non-zero to determine legal selectors, then +it will call the other functions to retrieve the name and pins of the group. +Maintaining the data structure of the groups is up to the driver, this is +just a simple example - in practice you may need more entries in your group +structure, for example specific register ranges associated with each group +and so on. + + +Interaction with the GPIO subsystem +=================================== + +The GPIO drivers may want to perform operations of various types on the same +physical pins that are also registered as pin controller pins. + +Since the pin controller subsystem have its pinspace local to the pin +controller we need a mapping so that the pin control subsystem can figure out +which pin controller handles control of a certain GPIO pin. Since a single +pin controller may be muxing several GPIO ranges (typically SoCs that have +one set of pins but internally several GPIO silicon blocks, each modeled as +a struct gpio_chip) any number of GPIO ranges can be added to a pin controller +instance like this: + +struct gpio_chip chip_a; +struct gpio_chip chip_b; + +static struct pinctrl_gpio_range gpio_range_a = { + .name = "chip a", + .id = 0, + .base = 32, + .npins = 16, + .gc = &chip_a; +}; + +static struct pinctrl_gpio_range gpio_range_a = { + .name = "chip b", + .id = 0, + .base = 48, + .npins = 8, + .gc = &chip_b; +}; + + +{ + struct pinctrl_dev *pctl; + ... + pinctrl_add_gpio_range(pctl, &gpio_range_a); + pinctrl_add_gpio_range(pctl, &gpio_range_b); +} + +So this complex system has one pin controller handling two different +GPIO chips. Chip a has 16 pins and chip b has 8 pins. They are mapped in +the global GPIO pin space at: + +chip a: [32 .. 47] +chip b: [48 .. 55] + +When GPIO-specific functions in the pin control subsystem are called, these +ranges will be used to look up the apropriate pin controller by inspecting +and matching the pin to the pin ranges across all controllers. When a +pin controller handling the matching range is found, GPIO-specific functions +will be called on that specific pin controller. + +For all functionalities dealing with pin biasing, pin muxing etc, the pin +controller subsystem will subtract the range's .base offset from the passed +in gpio pin number, and pass that on to the pin control driver, so the driver +will get an offset into its handled number range. Further it is also passed +the range ID value, so that the pin controller knows which range it should +deal with. + +For example: if a user issues pinctrl_gpio_set_foo(50), the pin control +subsystem will find that the second range on this pin controller matches, +subtract the base 48 and call the +pinctrl_driver_gpio_set_foo(pinctrl, range, 2) where the latter function has +this signature: + +int pinctrl_driver_gpio_set_foo(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *rangeid, + unsigned offset); + +Now the driver knows that we want to do some GPIO-specific operation on the +second GPIO range handled by "chip b", at offset 2 in that specific range. + +(If the GPIO subsystem is ever refactored to use a local per-GPIO controller +pin space, this mapping will need to be augmented accordingly.) + + +PINMUX interfaces +================= + +These calls use the pinmux_* naming prefix. No other calls should use that +prefix. + + +What is pinmuxing? +================== + +PINMUX, also known as padmux, ballmux, alternate functions or mission modes +is a way for chip vendors producing some kind of electrical packages to use +a certain physical pin (ball, pad, finger, etc) for multiple mutually exclusive +functions, depending on the application. By "application" in this context +we usually mean a way of soldering or wiring the package into an electronic +system, even though the framework makes it possible to also change the function +at runtime. + +Here is an example of a PGA (Pin Grid Array) chip seen from underneath: + + A B C D E F G H + +---+ + 8 | o | o o o o o o o + | | + 7 | o | o o o o o o o + | | + 6 | o | o o o o o o o + +---+---+ + 5 | o | o | o o o o o o + +---+---+ +---+ + 4 o o o o o o | o | o + | | + 3 o o o o o o | o | o + | | + 2 o o o o o o | o | o + +-------+-------+-------+---+---+ + 1 | o o | o o | o o | o | o | + +-------+-------+-------+---+---+ + +This is not tetris. The game to think of is chess. Not all PGA/BGA packages +are chessboard-like, big ones have "holes" in some arrangement according to +different design patterns, but we're using this as a simple example. Of the +pins you see some will be taken by things like a few VCC and GND to feed power +to the chip, and quite a few will be taken by large ports like an external +memory interface. The remaining pins will often be subject to pin multiplexing. + +The example 8x8 PGA package above will have pin numbers 0 thru 63 assigned to +its physical pins. It will name the pins { A1, A2, A3 ... H6, H7, H8 } using +pinctrl_register_pins() and a suitable data set as shown earlier. + +In this 8x8 BGA package the pins { A8, A7, A6, A5 } can be used as an SPI port +(these are four pins: CLK, RXD, TXD, FRM). In that case, pin B5 can be used as +some general-purpose GPIO pin. However, in another setting, pins { A5, B5 } can +be used as an I2C port (these are just two pins: SCL, SDA). Needless to say, +we cannot use the SPI port and I2C port at the same time. However in the inside +of the package the silicon performing the SPI logic can alternatively be routed +out on pins { G4, G3, G2, G1 }. + +On the botton row at { A1, B1, C1, D1, E1, F1, G1, H1 } we have something +special - it's an external MMC bus that can be 2, 4 or 8 bits wide, and it will +consume 2, 4 or 8 pins respectively, so either { A1, B1 } are taken or +{ A1, B1, C1, D1 } or all of them. If we use all 8 bits, we cannot use the SPI +port on pins { G4, G3, G2, G1 } of course. + +This way the silicon blocks present inside the chip can be multiplexed "muxed" +out on different pin ranges. Often contemporary SoC (systems on chip) will +contain several I2C, SPI, SDIO/MMC, etc silicon blocks that can be routed to +different pins by pinmux settings. + +Since general-purpose I/O pins (GPIO) are typically always in shortage, it is +common to be able to use almost any pin as a GPIO pin if it is not currently +in use by some other I/O port. + + +Pinmux conventions +================== + +The purpose of the pinmux functionality in the pin controller subsystem is to +abstract and provide pinmux settings to the devices you choose to instantiate +in your machine configuration. It is inspired by the clk, GPIO and regulator +subsystems, so devices will request their mux setting, but it's also possible +to request a single pin for e.g. GPIO. + +Definitions: + +- FUNCTIONS can be switched in and out by a driver residing with the pin + control subsystem in the drivers/pinctrl/* directory of the kernel. The + pin control driver knows the possible functions. In the example above you can + identify three pinmux functions, one for spi, one for i2c and one for mmc. + +- FUNCTIONS are assumed to be enumerable from zero in a one-dimensional array. + In this case the array could be something like: { spi0, i2c0, mmc0 } + for the three available functions. + +- FUNCTIONS have PIN GROUPS as defined on the generic level - so a certain + function is *always* associated with a certain set of pin groups, could + be just a single one, but could also be many. In the example above the + function i2c is associated with the pins { A5, B5 }, enumerated as + { 24, 25 } in the controller pin space. + + The Function spi is associated with pin groups { A8, A7, A6, A5 } + and { G4, G3, G2, G1 }, which are enumerated as { 0, 8, 16, 24 } and + { 38, 46, 54, 62 } respectively. + + Group names must be unique per pin controller, no two groups on the same + controller may have the same name. + +- The combination of a FUNCTION and a PIN GROUP determine a certain function + for a certain set of pins. The knowledge of the functions and pin groups + and their machine-specific particulars are kept inside the pinmux driver, + from the outside only the enumerators are known, and the driver core can: + + - Request the name of a function with a certain selector (>= 0) + - A list of groups associated with a certain function + - Request that a certain group in that list to be activated for a certain + function + + As already described above, pin groups are in turn self-descriptive, so + the core will retrieve the actual pin range in a certain group from the + driver. + +- FUNCTIONS and GROUPS on a certain PIN CONTROLLER are MAPPED to a certain + device by the board file, device tree or similar machine setup configuration + mechanism, similar to how regulators are connected to devices, usually by + name. Defining a pin controller, function and group thus uniquely identify + the set of pins to be used by a certain device. (If only one possible group + of pins is available for the function, no group name need to be supplied - + the core will simply select the first and only group available.) + + In the example case we can define that this particular machine shall + use device spi0 with pinmux function fspi0 group gspi0 and i2c0 on function + fi2c0 group gi2c0, on the primary pin controller, we get mappings + like these: + + { + {"map-spi0", spi0, pinctrl0, fspi0, gspi0}, + {"map-i2c0", i2c0, pinctrl0, fi2c0, gi2c0} + } + + Every map must be assigned a symbolic name, pin controller and function. + The group is not compulsory - if it is omitted the first group presented by + the driver as applicable for the function will be selected, which is + useful for simple cases. + + The device name is present in map entries tied to specific devices. Maps + without device names are referred to as SYSTEM pinmuxes, such as can be taken + by the machine implementation on boot and not tied to any specific device. + + It is possible to map several groups to the same combination of device, + pin controller and function. This is for cases where a certain function on + a certain pin controller may use different sets of pins in different + configurations. + +- PINS for a certain FUNCTION using a certain PIN GROUP on a certain + PIN CONTROLLER are provided on a first-come first-serve basis, so if some + other device mux setting or GPIO pin request has already taken your physical + pin, you will be denied the use of it. To get (activate) a new setting, the + old one has to be put (deactivated) first. + +Sometimes the documentation and hardware registers will be oriented around +pads (or "fingers") rather than pins - these are the soldering surfaces on the +silicon inside the package, and may or may not match the actual number of +pins/balls underneath the capsule. Pick some enumeration that makes sense to +you. Define enumerators only for the pins you can control if that makes sense. + +Assumptions: + +We assume that the number possible function maps to pin groups is limited by +the hardware. I.e. we assume that there is no system where any function can be +mapped to any pin, like in a phone exchange. So the available pins groups for +a certain function will be limited to a few choices (say up to eight or so), +not hundreds or any amount of choices. This is the characteristic we have found +by inspecting available pinmux hardware, and a necessary assumption since we +expect pinmux drivers to present *all* possible function vs pin group mappings +to the subsystem. + + +Pinmux drivers +============== + +The pinmux core takes care of preventing conflicts on pins and calling +the pin controller driver to execute different settings. + +It is the responsibility of the pinmux driver to impose further restrictions +(say for example infer electronic limitations due to load etc) to determine +whether or not the requested function can actually be allowed, and in case it +is possible to perform the requested mux setting, poke the hardware so that +this happens. + +Pinmux drivers are required to supply a few callback functions, some are +optional. Usually the enable() and disable() functions are implemented, +writing values into some certain registers to activate a certain mux setting +for a certain pin. + +A simple driver for the above example will work by setting bits 0, 1, 2, 3 or 4 +into some register named MUX to select a certain function with a certain +group of pins would work something like this: + +#include +#include + +struct foo_group { + const char *name; + const unsigned int *pins; + const unsigned num_pins; +}; + +static const unsigned spi0_0_pins[] = { 0, 8, 16, 24 }; +static const unsigned spi0_1_pins[] = { 38, 46, 54, 62 }; +static const unsigned i2c0_pins[] = { 24, 25 }; +static const unsigned mmc0_1_pins[] = { 56, 57 }; +static const unsigned mmc0_2_pins[] = { 58, 59 }; +static const unsigned mmc0_3_pins[] = { 60, 61, 62, 63 }; + +static const struct foo_group foo_groups[] = { + { + .name = "spi0_0_grp", + .pins = spi0_0_pins, + .num_pins = ARRAY_SIZE(spi0_0_pins), + }, + { + .name = "spi0_1_grp", + .pins = spi0_1_pins, + .num_pins = ARRAY_SIZE(spi0_1_pins), + }, + { + .name = "i2c0_grp", + .pins = i2c0_pins, + .num_pins = ARRAY_SIZE(i2c0_pins), + }, + { + .name = "mmc0_1_grp", + .pins = mmc0_1_pins, + .num_pins = ARRAY_SIZE(mmc0_1_pins), + }, + { + .name = "mmc0_2_grp", + .pins = mmc0_2_pins, + .num_pins = ARRAY_SIZE(mmc0_2_pins), + }, + { + .name = "mmc0_3_grp", + .pins = mmc0_3_pins, + .num_pins = ARRAY_SIZE(mmc0_3_pins), + }, +}; + + +static int foo_list_groups(struct pinctrl_dev *pctldev, unsigned selector) +{ + if (selector >= ARRAY_SIZE(foo_groups)) + return -EINVAL; + return 0; +} + +static const char *foo_get_group_name(struct pinctrl_dev *pctldev, + unsigned selector) +{ + return foo_groups[selector].name; +} + +static int foo_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector, + unsigned ** const pins, + unsigned * const num_pins) +{ + *pins = (unsigned *) foo_groups[selector].pins; + *num_pins = foo_groups[selector].num_pins; + return 0; +} + +static struct pinctrl_ops foo_pctrl_ops = { + .list_groups = foo_list_groups, + .get_group_name = foo_get_group_name, + .get_group_pins = foo_get_group_pins, +}; + +struct foo_pmx_func { + const char *name; + const char * const *groups; + const unsigned num_groups; +}; + +static const char * const spi0_groups[] = { "spi0_1_grp" }; +static const char * const i2c0_groups[] = { "i2c0_grp" }; +static const char * const mmc0_groups[] = { "mmc0_1_grp", "mmc0_2_grp", + "mmc0_3_grp" }; + +static const struct foo_pmx_func foo_functions[] = { + { + .name = "spi0", + .groups = spi0_groups, + .num_groups = ARRAY_SIZE(spi0_groups), + }, + { + .name = "i2c0", + .groups = i2c0_groups, + .num_groups = ARRAY_SIZE(i2c0_groups), + }, + { + .name = "mmc0", + .groups = mmc0_groups, + .num_groups = ARRAY_SIZE(mmc0_groups), + }, +}; + +int foo_list_funcs(struct pinctrl_dev *pctldev, unsigned selector) +{ + if (selector >= ARRAY_SIZE(foo_functions)) + return -EINVAL; + return 0; +} + +const char *foo_get_fname(struct pinctrl_dev *pctldev, unsigned selector) +{ + return myfuncs[selector].name; +} + +static int foo_get_groups(struct pinctrl_dev *pctldev, unsigned selector, + const char * const **groups, + unsigned * const num_groups) +{ + *groups = foo_functions[selector].groups; + *num_groups = foo_functions[selector].num_groups; + return 0; +} + +int foo_enable(struct pinctrl_dev *pctldev, unsigned selector, + unsigned group) +{ + u8 regbit = (1 << group); + + writeb((readb(MUX)|regbit), MUX) + return 0; +} + +int foo_disable(struct pinctrl_dev *pctldev, unsigned selector, + unsigned group) +{ + u8 regbit = (1 << group); + + writeb((readb(MUX) & ~(regbit)), MUX) + return 0; +} + +struct pinmux_ops foo_pmxops = { + .list_functions = foo_list_funcs, + .get_function_name = foo_get_fname, + .get_function_groups = foo_get_groups, + .enable = foo_enable, + .disable = foo_disable, +}; + +/* Pinmux operations are handled by some pin controller */ +static struct pinctrl_desc foo_desc = { + ... + .pctlops = &foo_pctrl_ops, + .pmxops = &foo_pmxops, +}; + +In the example activating muxing 0 and 1 at the same time setting bits +0 and 1, uses one pin in common so they would collide. + +The beauty of the pinmux subsystem is that since it keeps track of all +pins and who is using them, it will already have denied an impossible +request like that, so the driver does not need to worry about such +things - when it gets a selector passed in, the pinmux subsystem makes +sure no other device or GPIO assignment is already using the selected +pins. Thus bits 0 and 1 in the control register will never be set at the +same time. + +All the above functions are mandatory to implement for a pinmux driver. + + +Pinmux interaction with the GPIO subsystem +========================================== + +The function list could become long, especially if you can convert every +individual pin into a GPIO pin independent of any other pins, and then try +the approach to define every pin as a function. + +In this case, the function array would become 64 entries for each GPIO +setting and then the device functions. + +For this reason there is an additional function a pinmux driver can implement +to enable only GPIO on an individual pin: .gpio_request_enable(). The same +.free() function as for other functions is assumed to be usable also for +GPIO pins. + +This function will pass in the affected GPIO range identified by the pin +controller core, so you know which GPIO pins are being affected by the request +operation. + +Alternatively it is fully allowed to use named functions for each GPIO +pin, the pinmux_request_gpio() will attempt to obtain the function "gpioN" +where "N" is the global GPIO pin number if no special GPIO-handler is +registered. + + +Pinmux board/machine configuration +================================== + +Boards and machines define how a certain complete running system is put +together, including how GPIOs and devices are muxed, how regulators are +constrained and how the clock tree looks. Of course pinmux settings are also +part of this. + +A pinmux config for a machine looks pretty much like a simple regulator +configuration, so for the example array above we want to enable i2c and +spi on the second function mapping: + +#include + +static struct pinmux_map pmx_mapping[] = { + { + .ctrl_dev_name = "pinctrl.0", + .function = "spi0", + .dev_name = "foo-spi.0", + }, + { + .ctrl_dev_name = "pinctrl.0", + .function = "i2c0", + .dev_name = "foo-i2c.0", + }, + { + .ctrl_dev_name = "pinctrl.0", + .function = "mmc0", + .dev_name = "foo-mmc.0", + }, +}; + +The dev_name here matches to the unique device name that can be used to look +up the device struct (just like with clockdev or regulators). The function name +must match a function provided by the pinmux driver handling this pin range. + +As you can see we may have several pin controllers on the system and thus +we need to specify which one of them that contain the functions we wish +to map. The map can also use struct device * directly, so there is no +inherent need to use strings to specify .dev_name or .ctrl_dev_name, these +are for the situation where you do not have a handle to the struct device *, +for example if they are not yet instantiated or cumbersome to obtain. + +You register this pinmux mapping to the pinmux subsystem by simply: + + ret = pinmux_register_mappings(&pmx_mapping, ARRAY_SIZE(pmx_mapping)); + +Since the above construct is pretty common there is a helper macro to make +it even more compact which assumes you want to use pinctrl.0 and position +0 for mapping, for example: + +static struct pinmux_map pmx_mapping[] = { + PINMUX_MAP_PRIMARY("I2CMAP", "i2c0", "foo-i2c.0"), +}; + + +Complex mappings +================ + +As it is possible to map a function to different groups of pins an optional +.group can be specified like this: + +... +{ + .name = "spi0-pos-A", + .ctrl_dev_name = "pinctrl.0", + .function = "spi0", + .group = "spi0_0_grp", + .dev_name = "foo-spi.0", +}, +{ + .name = "spi0-pos-B", + .ctrl_dev_name = "pinctrl.0", + .function = "spi0", + .group = "spi0_1_grp", + .dev_name = "foo-spi.0", +}, +... + +This example mapping is used to switch between two positions for spi0 at +runtime, as described further below under the heading "Runtime pinmuxing". + +Further it is possible to match several groups of pins to the same function +for a single device, say for example in the mmc0 example above, where you can +additively expand the mmc0 bus from 2 to 4 to 8 pins. If we want to use all +three groups for a total of 2+2+4 = 8 pins (for an 8-bit MMC bus as is the +case), we define a mapping like this: + +... +{ + .name "2bit" + .ctrl_dev_name = "pinctrl.0", + .function = "mmc0", + .group = "mmc0_0_grp", + .dev_name = "foo-mmc.0", +}, +{ + .name "4bit" + .ctrl_dev_name = "pinctrl.0", + .function = "mmc0", + .group = "mmc0_0_grp", + .dev_name = "foo-mmc.0", +}, +{ + .name "4bit" + .ctrl_dev_name = "pinctrl.0", + .function = "mmc0", + .group = "mmc0_1_grp", + .dev_name = "foo-mmc.0", +}, +{ + .name "8bit" + .ctrl_dev_name = "pinctrl.0", + .function = "mmc0", + .group = "mmc0_0_grp", + .dev_name = "foo-mmc.0", +}, +{ + .name "8bit" + .ctrl_dev_name = "pinctrl.0", + .function = "mmc0", + .group = "mmc0_1_grp", + .dev_name = "foo-mmc.0", +}, +{ + .name "8bit" + .ctrl_dev_name = "pinctrl.0", + .function = "mmc0", + .group = "mmc0_2_grp", + .dev_name = "foo-mmc.0", +}, +... + +The result of grabbing this mapping from the device with something like +this (see next paragraph): + + pmx = pinmux_get(&device, "8bit"); + +Will be that you activate all the three bottom records in the mapping at +once. Since they share the same name, pin controller device, funcion and +device, and since we allow multiple groups to match to a single device, they +all get selected, and they all get enabled and disable simultaneously by the +pinmux core. + + +Pinmux requests from drivers +============================ + +Generally it is discouraged to let individual drivers get and enable pinmuxes. +So if possible, handle the pinmuxes in platform code or some other place where +you have access to all the affected struct device * pointers. In some cases +where a driver needs to switch between different mux mappings at runtime +this is not possible. + +A driver may request a certain mux to be activated, usually just the default +mux like this: + +#include + +struct foo_state { + struct pinmux *pmx; + ... +}; + +foo_probe() +{ + /* Allocate a state holder named "state" etc */ + struct pinmux pmx; + + pmx = pinmux_get(&device, NULL); + if IS_ERR(pmx) + return PTR_ERR(pmx); + pinmux_enable(pmx); + + state->pmx = pmx; +} + +foo_remove() +{ + pinmux_disable(state->pmx); + pinmux_put(state->pmx); +} + +If you want to grab a specific mux mapping and not just the first one found for +this device you can specify a specific mapping name, for example in the above +example the second i2c0 setting: pinmux_get(&device, "spi0-pos-B"); + +This get/enable/disable/put sequence can just as well be handled by bus drivers +if you don't want each and every driver to handle it and you know the +arrangement on your bus. + +The semantics of the get/enable respective disable/put is as follows: + +- pinmux_get() is called in process context to reserve the pins affected with + a certain mapping and set up the pinmux core and the driver. It will allocate + a struct from the kernel memory to hold the pinmux state. + +- pinmux_enable()/pinmux_disable() is quick and can be called from fastpath + (irq context) when you quickly want to set up/tear down the hardware muxing + when running a device driver. Usually it will just poke some values into a + register. + +- pinmux_disable() is called in process context to tear down the pin requests + and release the state holder struct for the mux setting. + +Usually the pinmux core handled the get/put pair and call out to the device +drivers bookkeeping operations, like checking available functions and the +associated pins, whereas the enable/disable pass on to the pin controller +driver which takes care of activating and/or deactivating the mux setting by +quickly poking some registers. + +The pins are allocated for your device when you issue the pinmux_get() call, +after this you should be able to see this in the debugfs listing of all pins. + + +System pinmux hogging +===================== + +A system pinmux map entry, i.e. a pinmux setting that does not have a device +associated with it, can be hogged by the core when the pin controller is +registered. This means that the core will attempt to call pinmux_get() and +pinmux_enable() on it immediately after the pin control device has been +registered. + +This is enabled by simply setting the .hog_on_boot field in the map to true, +like this: + +{ + .name "POWERMAP" + .ctrl_dev_name = "pinctrl.0", + .function = "power_func", + .hog_on_boot = true, +}, + +Since it may be common to request the core to hog a few always-applicable +mux settings on the primary pin controller, there is a convenience macro for +this: + +PINMUX_MAP_PRIMARY_SYS_HOG("POWERMAP", "power_func") + +This gives the exact same result as the above construction. + + +Runtime pinmuxing +================= + +It is possible to mux a certain function in and out at runtime, say to move +an SPI port from one set of pins to another set of pins. Say for example for +spi0 in the example above, we expose two different groups of pins for the same +function, but with different named in the mapping as described under +"Advanced mapping" above. So we have two mappings named "spi0-pos-A" and +"spi0-pos-B". + +This snippet first muxes the function in the pins defined by group A, enables +it, disables and releases it, and muxes it in on the pins defined by group B: + +foo_switch() +{ + struct pinmux pmx; + + /* Enable on position A */ + pmx = pinmux_get(&device, "spi0-pos-A"); + if IS_ERR(pmx) + return PTR_ERR(pmx); + pinmux_enable(pmx); + + /* This releases the pins again */ + pinmux_disable(pmx); + pinmux_put(pmx); + + /* Enable on position B */ + pmx = pinmux_get(&device, "spi0-pos-B"); + if IS_ERR(pmx) + return PTR_ERR(pmx); + pinmux_enable(pmx); + ... +} + +The above has to be done from process context. diff --git a/Documentation/power/00-INDEX b/Documentation/power/00-INDEX index 45e9d4a91284678e9a9acf55ab5a23b07d17ce33..a4d682f54231d01eafdbb23ebab39d571a409c52 100644 --- a/Documentation/power/00-INDEX +++ b/Documentation/power/00-INDEX @@ -26,6 +26,8 @@ s2ram.txt - How to get suspend to ram working (and debug it when it isn't) states.txt - System power management states +suspend-and-cpuhotplug.txt + - Explains the interaction between Suspend-to-RAM (S3) and CPU hotplug swsusp-and-swap-files.txt - Using swap files with software suspend (to disk) swsusp-dmcrypt.txt diff --git a/Documentation/power/basic-pm-debugging.txt b/Documentation/power/basic-pm-debugging.txt index ddd78172ef738d2c3f52dcea70f61cb0591670c2..40a4c65f380a10479a7a805d58310be97b1a2ee1 100644 --- a/Documentation/power/basic-pm-debugging.txt +++ b/Documentation/power/basic-pm-debugging.txt @@ -173,7 +173,7 @@ kernel messages using the serial console. This may provide you with some information about the reasons of the suspend (resume) failure. Alternatively, it may be possible to use a FireWire port for debugging with firescope (ftp://ftp.firstfloor.org/pub/ak/firescope/). On x86 it is also possible to -use the PM_TRACE mechanism documented in Documentation/s2ram.txt . +use the PM_TRACE mechanism documented in Documentation/power/s2ram.txt . 2. Testing suspend to RAM (STR) @@ -201,3 +201,27 @@ case, you may be able to search for failing drivers by following the procedure analogous to the one described in section 1. If you find some failing drivers, you will have to unload them every time before an STR transition (ie. before you run s2ram), and please report the problems with them. + +There is a debugfs entry which shows the suspend to RAM statistics. Here is an +example of its output. + # mount -t debugfs none /sys/kernel/debug + # cat /sys/kernel/debug/suspend_stats + success: 20 + fail: 5 + failed_freeze: 0 + failed_prepare: 0 + failed_suspend: 5 + failed_suspend_noirq: 0 + failed_resume: 0 + failed_resume_noirq: 0 + failures: + last_failed_dev: alarm + adc + last_failed_errno: -16 + -16 + last_failed_step: suspend + suspend +Field success means the success number of suspend to RAM, and field fail means +the failure number. Others are the failure number of different steps of suspend +to RAM. suspend_stats just lists the last 2 failed devices, error number and +failed step of suspend. diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt index 3384d5996be2a199031e377ef832f6a9ecc6066e..646a89e0c07d50c682912ef0200dc087363cd37f 100644 --- a/Documentation/power/devices.txt +++ b/Documentation/power/devices.txt @@ -152,7 +152,9 @@ try to use its wakeup mechanism. device_set_wakeup_enable() affects this flag; for the most part drivers should not change its value. The initial value of should_wakeup is supposed to be false for the majority of devices; the major exceptions are power buttons, keyboards, and Ethernet adapters whose WoL -(wake-on-LAN) feature has been set up with ethtool. +(wake-on-LAN) feature has been set up with ethtool. It should also default +to true for devices that don't generate wakeup requests on their own but merely +forward wakeup requests from one bus to another (like PCI bridges). Whether or not a device is capable of issuing wakeup events is a hardware matter, and the kernel is responsible for keeping track of it. By contrast, @@ -279,10 +281,6 @@ When the system goes into the standby or memory sleep state, the phases are: time.) Unlike the other suspend-related phases, during the prepare phase the device tree is traversed top-down. - In addition to that, if device drivers need to allocate additional - memory to be able to hadle device suspend correctly, that should be - done in the prepare phase. - After the prepare callback method returns, no new children may be registered below the device. The method may also prepare the device or driver in some way for the upcoming system power transition (for diff --git a/Documentation/power/pm_qos_interface.txt b/Documentation/power/pm_qos_interface.txt index bfed898a03fcc292af8dcb55132b015010c382d0..17e130a803470377ba898d069b84f8b0f51eda69 100644 --- a/Documentation/power/pm_qos_interface.txt +++ b/Documentation/power/pm_qos_interface.txt @@ -4,14 +4,19 @@ This interface provides a kernel and user mode interface for registering performance expectations by drivers, subsystems and user space applications on one of the parameters. -Currently we have {cpu_dma_latency, network_latency, network_throughput} as the -initial set of pm_qos parameters. +Two different PM QoS frameworks are available: +1. PM QoS classes for cpu_dma_latency, network_latency, network_throughput. +2. the per-device PM QoS framework provides the API to manage the per-device latency +constraints. Each parameters have defined units: * latency: usec * timeout: usec * throughput: kbs (kilo bit / sec) + +1. PM QoS framework + The infrastructure exposes multiple misc device nodes one per implemented parameter. The set of parameters implement is defined by pm_qos_power_init() and pm_qos_params.h. This is done because having the available parameters @@ -23,14 +28,18 @@ an aggregated target value. The aggregated target value is updated with changes to the request list or elements of the list. Typically the aggregated target value is simply the max or min of the request values held in the parameter list elements. +Note: the aggregated target value is implemented as an atomic variable so that +reading the aggregated value does not require any locking mechanism. + From kernel mode the use of this interface is simple: -handle = pm_qos_add_request(param_class, target_value): -Will insert an element into the list for that identified PM_QOS class with the +void pm_qos_add_request(handle, param_class, target_value): +Will insert an element into the list for that identified PM QoS class with the target value. Upon change to this list the new target is recomputed and any registered notifiers are called only if the target value is now different. -Clients of pm_qos need to save the returned handle. +Clients of pm_qos need to save the returned handle for future use in other +pm_qos API functions. void pm_qos_update_request(handle, new_target_value): Will update the list element pointed to by the handle with the new target value @@ -42,6 +51,20 @@ Will remove the element. After removal it will update the aggregate target and call the notification tree if the target was changed as a result of removing the request. +int pm_qos_request(param_class): +Returns the aggregated value for a given PM QoS class. + +int pm_qos_request_active(handle): +Returns if the request is still active, i.e. it has not been removed from a +PM QoS class constraints list. + +int pm_qos_add_notifier(param_class, notifier): +Adds a notification callback function to the PM QoS class. The callback is +called when the aggregated value for the PM QoS class is changed. + +int pm_qos_remove_notifier(int param_class, notifier): +Removes the notification callback function for the PM QoS class. + From user mode: Only processes can register a pm_qos request. To provide for automatic @@ -63,4 +86,63 @@ To remove the user mode request for a target value simply close the device node. +2. PM QoS per-device latency framework + +For each device a list of performance requests is maintained along with +an aggregated target value. The aggregated target value is updated with +changes to the request list or elements of the list. Typically the +aggregated target value is simply the max or min of the request values held +in the parameter list elements. +Note: the aggregated target value is implemented as an atomic variable so that +reading the aggregated value does not require any locking mechanism. + + +From kernel mode the use of this interface is the following: + +int dev_pm_qos_add_request(device, handle, value): +Will insert an element into the list for that identified device with the +target value. Upon change to this list the new target is recomputed and any +registered notifiers are called only if the target value is now different. +Clients of dev_pm_qos need to save the handle for future use in other +dev_pm_qos API functions. + +int dev_pm_qos_update_request(handle, new_value): +Will update the list element pointed to by the handle with the new target value +and recompute the new aggregated target, calling the notification trees if the +target is changed. + +int dev_pm_qos_remove_request(handle): +Will remove the element. After removal it will update the aggregate target and +call the notification trees if the target was changed as a result of removing +the request. + +s32 dev_pm_qos_read_value(device): +Returns the aggregated value for a given device's constraints list. + + +Notification mechanisms: +The per-device PM QoS framework has 2 different and distinct notification trees: +a per-device notification tree and a global notification tree. + +int dev_pm_qos_add_notifier(device, notifier): +Adds a notification callback function for the device. +The callback is called when the aggregated value of the device constraints list +is changed. + +int dev_pm_qos_remove_notifier(device, notifier): +Removes the notification callback function for the device. + +int dev_pm_qos_add_global_notifier(notifier): +Adds a notification callback function in the global notification tree of the +framework. +The callback is called when the aggregated value for any device is changed. + +int dev_pm_qos_remove_global_notifier(notifier): +Removes the notification callback function from the global notification tree +of the framework. + + +From user mode: +No API for user space access to the per-device latency constraints is provided +yet - still under discussion. diff --git a/Documentation/power/regulator/machine.txt b/Documentation/power/regulator/machine.txt index b42419b52e444063841bcd6f0571ea0cde1eca84..ce63af0a8e35ecab32e2f326d13a9a2b33b62909 100644 --- a/Documentation/power/regulator/machine.txt +++ b/Documentation/power/regulator/machine.txt @@ -16,7 +16,7 @@ initialisation code by creating a struct regulator_consumer_supply for each regulator. struct regulator_consumer_supply { - struct device *dev; /* consumer */ + const char *dev_name; /* consumer dev_name() */ const char *supply; /* consumer supply - e.g. "vcc" */ }; @@ -24,13 +24,13 @@ e.g. for the machine above static struct regulator_consumer_supply regulator1_consumers[] = { { - .dev = &platform_consumerB_device.dev, - .supply = "Vcc", + .dev_name = "dev_name(consumer B)", + .supply = "Vcc", },}; static struct regulator_consumer_supply regulator2_consumers[] = { { - .dev = &platform_consumerA_device.dev, + .dev = "dev_name(consumer A"), .supply = "Vcc", },}; @@ -43,6 +43,7 @@ to their supply regulator :- static struct regulator_init_data regulator1_data = { .constraints = { + .name = "Regulator-1", .min_uV = 3300000, .max_uV = 3300000, .valid_modes_mask = REGULATOR_MODE_NORMAL, @@ -51,13 +52,19 @@ static struct regulator_init_data regulator1_data = { .consumer_supplies = regulator1_consumers, }; +The name field should be set to something that is usefully descriptive +for the board for configuration of supplies for other regulators and +for use in logging and other diagnostic output. Normally the name +used for the supply rail in the schematic is a good choice. If no +name is provided then the subsystem will choose one. + Regulator-1 supplies power to Regulator-2. This relationship must be registered with the core so that Regulator-1 is also enabled when Consumer A enables its supply (Regulator-2). The supply regulator is set by the supply_regulator -field below:- +field below and co:- static struct regulator_init_data regulator2_data = { - .supply_regulator = "regulator_name", + .supply_regulator = "Regulator-1", .constraints = { .min_uV = 1800000, .max_uV = 2000000, diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt index 6066e3a6b9a98c0f499059d1342444afb43be781..0e856088db7c87b66d2284aaabb03501bea95415 100644 --- a/Documentation/power/runtime_pm.txt +++ b/Documentation/power/runtime_pm.txt @@ -43,13 +43,18 @@ struct dev_pm_ops { ... }; -The ->runtime_suspend(), ->runtime_resume() and ->runtime_idle() callbacks are -executed by the PM core for either the device type, or the class (if the device -type's struct dev_pm_ops object does not exist), or the bus type (if the -device type's and class' struct dev_pm_ops objects do not exist) of the given -device (this allows device types to override callbacks provided by bus types or -classes if necessary). The bus type, device type and class callbacks are -referred to as subsystem-level callbacks in what follows. +The ->runtime_suspend(), ->runtime_resume() and ->runtime_idle() callbacks +are executed by the PM core for either the power domain, or the device type +(if the device power domain's struct dev_pm_ops does not exist), or the class +(if the device power domain's and type's struct dev_pm_ops object does not +exist), or the bus type (if the device power domain's, type's and class' +struct dev_pm_ops objects do not exist) of the given device, so the priority +order of callbacks from high to low is that power domain callbacks, device +type callbacks, class callbacks and bus type callbacks, and the high priority +one will take precedence over low priority one. The bus type, device type and +class callbacks are referred to as subsystem-level callbacks in what follows, +and generally speaking, the power domain callbacks are used for representing +power domains within a SoC. By default, the callbacks are always invoked in process context with interrupts enabled. However, subsystems can use the pm_runtime_irq_safe() helper function @@ -477,12 +482,14 @@ pm_runtime_autosuspend_expiration() If pm_runtime_irq_safe() has been called for a device then the following helper functions may also be used in interrupt context: +pm_runtime_idle() pm_runtime_suspend() pm_runtime_autosuspend() pm_runtime_resume() pm_runtime_get_sync() pm_runtime_put_sync() pm_runtime_put_sync_suspend() +pm_runtime_put_sync_autosuspend() 5. Runtime PM Initialization, Device Probing and Removal diff --git a/Documentation/power/suspend-and-cpuhotplug.txt b/Documentation/power/suspend-and-cpuhotplug.txt new file mode 100644 index 0000000000000000000000000000000000000000..f28f9a6f03472fb8915d965f792b9827c513fd8b --- /dev/null +++ b/Documentation/power/suspend-and-cpuhotplug.txt @@ -0,0 +1,275 @@ +Interaction of Suspend code (S3) with the CPU hotplug infrastructure + + (C) 2011 Srivatsa S. Bhat + + +I. How does the regular CPU hotplug code differ from how the Suspend-to-RAM + infrastructure uses it internally? And where do they share common code? + +Well, a picture is worth a thousand words... So ASCII art follows :-) + +[This depicts the current design in the kernel, and focusses only on the +interactions involving the freezer and CPU hotplug and also tries to explain +the locking involved. It outlines the notifications involved as well. +But please note that here, only the call paths are illustrated, with the aim +of describing where they take different paths and where they share code. +What happens when regular CPU hotplug and Suspend-to-RAM race with each other +is not depicted here.] + +On a high level, the suspend-resume cycle goes like this: + +|Freeze| -> |Disable nonboot| -> |Do suspend| -> |Enable nonboot| -> |Thaw | +|tasks | | cpus | | | | cpus | |tasks| + + +More details follow: + + Suspend call path + ----------------- + + Write 'mem' to + /sys/power/state + syfs file + | + v + Acquire pm_mutex lock + | + v + Send PM_SUSPEND_PREPARE + notifications + | + v + Freeze tasks + | + | + v + disable_nonboot_cpus() + /* start */ + | + v + Acquire cpu_add_remove_lock + | + v + Iterate over CURRENTLY + online CPUs + | + | + | ---------- + v | L + ======> _cpu_down() | + | [This takes cpuhotplug.lock | + Common | before taking down the CPU | + code | and releases it when done] | O + | While it is at it, notifications | + | are sent when notable events occur, | + ======> by running all registered callbacks. | + | | O + | | + | | + v | + Note down these cpus in | P + frozen_cpus mask ---------- + | + v + Disable regular cpu hotplug + by setting cpu_hotplug_disabled=1 + | + v + Release cpu_add_remove_lock + | + v + /* disable_nonboot_cpus() complete */ + | + v + Do suspend + + + +Resuming back is likewise, with the counterparts being (in the order of +execution during resume): +* enable_nonboot_cpus() which involves: + | Acquire cpu_add_remove_lock + | Reset cpu_hotplug_disabled to 0, thereby enabling regular cpu hotplug + | Call _cpu_up() [for all those cpus in the frozen_cpus mask, in a loop] + | Release cpu_add_remove_lock + v + +* thaw tasks +* send PM_POST_SUSPEND notifications +* Release pm_mutex lock. + + +It is to be noted here that the pm_mutex lock is acquired at the very +beginning, when we are just starting out to suspend, and then released only +after the entire cycle is complete (i.e., suspend + resume). + + + + Regular CPU hotplug call path + ----------------------------- + + Write 0 (or 1) to + /sys/devices/system/cpu/cpu*/online + sysfs file + | + | + v + cpu_down() + | + v + Acquire cpu_add_remove_lock + | + v + If cpu_hotplug_disabled is 1 + return gracefully + | + | + v + ======> _cpu_down() + | [This takes cpuhotplug.lock + Common | before taking down the CPU + code | and releases it when done] + | While it is at it, notifications + | are sent when notable events occur, + ======> by running all registered callbacks. + | + | + v + Release cpu_add_remove_lock + [That's it!, for + regular CPU hotplug] + + + +So, as can be seen from the two diagrams (the parts marked as "Common code"), +regular CPU hotplug and the suspend code path converge at the _cpu_down() and +_cpu_up() functions. They differ in the arguments passed to these functions, +in that during regular CPU hotplug, 0 is passed for the 'tasks_frozen' +argument. But during suspend, since the tasks are already frozen by the time +the non-boot CPUs are offlined or onlined, the _cpu_*() functions are called +with the 'tasks_frozen' argument set to 1. +[See below for some known issues regarding this.] + + +Important files and functions/entry points: +------------------------------------------ + +kernel/power/process.c : freeze_processes(), thaw_processes() +kernel/power/suspend.c : suspend_prepare(), suspend_enter(), suspend_finish() +kernel/cpu.c: cpu_[up|down](), _cpu_[up|down](), [disable|enable]_nonboot_cpus() + + + +II. What are the issues involved in CPU hotplug? + ------------------------------------------- + +There are some interesting situations involving CPU hotplug and microcode +update on the CPUs, as discussed below: + +[Please bear in mind that the kernel requests the microcode images from +userspace, using the request_firmware() function defined in +drivers/base/firmware_class.c] + + +a. When all the CPUs are identical: + + This is the most common situation and it is quite straightforward: we want + to apply the same microcode revision to each of the CPUs. + To give an example of x86, the collect_cpu_info() function defined in + arch/x86/kernel/microcode_core.c helps in discovering the type of the CPU + and thereby in applying the correct microcode revision to it. + But note that the kernel does not maintain a common microcode image for the + all CPUs, in order to handle case 'b' described below. + + +b. When some of the CPUs are different than the rest: + + In this case since we probably need to apply different microcode revisions + to different CPUs, the kernel maintains a copy of the correct microcode + image for each CPU (after appropriate CPU type/model discovery using + functions such as collect_cpu_info()). + + +c. When a CPU is physically hot-unplugged and a new (and possibly different + type of) CPU is hot-plugged into the system: + + In the current design of the kernel, whenever a CPU is taken offline during + a regular CPU hotplug operation, upon receiving the CPU_DEAD notification + (which is sent by the CPU hotplug code), the microcode update driver's + callback for that event reacts by freeing the kernel's copy of the + microcode image for that CPU. + + Hence, when a new CPU is brought online, since the kernel finds that it + doesn't have the microcode image, it does the CPU type/model discovery + afresh and then requests the userspace for the appropriate microcode image + for that CPU, which is subsequently applied. + + For example, in x86, the mc_cpu_callback() function (which is the microcode + update driver's callback registered for CPU hotplug events) calls + microcode_update_cpu() which would call microcode_init_cpu() in this case, + instead of microcode_resume_cpu() when it finds that the kernel doesn't + have a valid microcode image. This ensures that the CPU type/model + discovery is performed and the right microcode is applied to the CPU after + getting it from userspace. + + +d. Handling microcode update during suspend/hibernate: + + Strictly speaking, during a CPU hotplug operation which does not involve + physically removing or inserting CPUs, the CPUs are not actually powered + off during a CPU offline. They are just put to the lowest C-states possible. + Hence, in such a case, it is not really necessary to re-apply microcode + when the CPUs are brought back online, since they wouldn't have lost the + image during the CPU offline operation. + + This is the usual scenario encountered during a resume after a suspend. + However, in the case of hibernation, since all the CPUs are completely + powered off, during restore it becomes necessary to apply the microcode + images to all the CPUs. + + [Note that we don't expect someone to physically pull out nodes and insert + nodes with a different type of CPUs in-between a suspend-resume or a + hibernate/restore cycle.] + + In the current design of the kernel however, during a CPU offline operation + as part of the suspend/hibernate cycle (the CPU_DEAD_FROZEN notification), + the existing copy of microcode image in the kernel is not freed up. + And during the CPU online operations (during resume/restore), since the + kernel finds that it already has copies of the microcode images for all the + CPUs, it just applies them to the CPUs, avoiding any re-discovery of CPU + type/model and the need for validating whether the microcode revisions are + right for the CPUs or not (due to the above assumption that physical CPU + hotplug will not be done in-between suspend/resume or hibernate/restore + cycles). + + +III. Are there any known problems when regular CPU hotplug and suspend race + with each other? + +Yes, they are listed below: + +1. When invoking regular CPU hotplug, the 'tasks_frozen' argument passed to + the _cpu_down() and _cpu_up() functions is *always* 0. + This might not reflect the true current state of the system, since the + tasks could have been frozen by an out-of-band event such as a suspend + operation in progress. Hence, it will lead to wrong notifications being + sent during the cpu online/offline events (eg, CPU_ONLINE notification + instead of CPU_ONLINE_FROZEN) which in turn will lead to execution of + inappropriate code by the callbacks registered for such CPU hotplug events. + +2. If a regular CPU hotplug stress test happens to race with the freezer due + to a suspend operation in progress at the same time, then we could hit the + situation described below: + + * A regular cpu online operation continues its journey from userspace + into the kernel, since the freezing has not yet begun. + * Then freezer gets to work and freezes userspace. + * If cpu online has not yet completed the microcode update stuff by now, + it will now start waiting on the frozen userspace in the + TASK_UNINTERRUPTIBLE state, in order to get the microcode image. + * Now the freezer continues and tries to freeze the remaining tasks. But + due to this wait mentioned above, the freezer won't be able to freeze + the cpu online hotplug task and hence freezing of tasks fails. + + As a result of this task freezing failure, the suspend operation gets + aborted. diff --git a/Documentation/power/userland-swsusp.txt b/Documentation/power/userland-swsusp.txt index 1101bee4e822366203e7b394be09294ac07a957a..0e870825c1b97b4d53b199e7eae050926e13b35f 100644 --- a/Documentation/power/userland-swsusp.txt +++ b/Documentation/power/userland-swsusp.txt @@ -77,7 +77,8 @@ SNAPSHOT_SET_SWAP_AREA - set the resume partition and the offset (in resume_swap_area, as defined in kernel/power/suspend_ioctls.h, containing the resume device specification and the offset); for swap partitions the offset is always 0, but it is different from zero for - swap files (see Documentation/swsusp-and-swap-files.txt for details). + swap files (see Documentation/power/swsusp-and-swap-files.txt for + details). SNAPSHOT_PLATFORM_SUPPORT - enable/disable the hibernation platform support, depending on the argument value (enable, if the argument is nonzero) diff --git a/Documentation/rfkill.txt b/Documentation/rfkill.txt index 83668e5dd17f4b23dff1dfbb50ebe049c788a8a8..03c9d9299c6b1fb55ed48f89f146d4029b323f22 100644 --- a/Documentation/rfkill.txt +++ b/Documentation/rfkill.txt @@ -117,5 +117,4 @@ The contents of these variables corresponds to the "name", "state" and "type" sysfs files explained above. -For further details consult Documentation/ABI/stable/dev-rfkill and -Documentation/ABI/stable/sysfs-class-rfkill. +For further details consult Documentation/ABI/stable/sysfs-class-rfkill. diff --git a/Documentation/scheduler/sched-bwc.txt b/Documentation/scheduler/sched-bwc.txt new file mode 100644 index 0000000000000000000000000000000000000000..f6b1873f68abc695d0e10ddac6e94c4b4042bda8 --- /dev/null +++ b/Documentation/scheduler/sched-bwc.txt @@ -0,0 +1,122 @@ +CFS Bandwidth Control +===================== + +[ This document only discusses CPU bandwidth control for SCHED_NORMAL. + The SCHED_RT case is covered in Documentation/scheduler/sched-rt-group.txt ] + +CFS bandwidth control is a CONFIG_FAIR_GROUP_SCHED extension which allows the +specification of the maximum CPU bandwidth available to a group or hierarchy. + +The bandwidth allowed for a group is specified using a quota and period. Within +each given "period" (microseconds), a group is allowed to consume only up to +"quota" microseconds of CPU time. When the CPU bandwidth consumption of a +group exceeds this limit (for that period), the tasks belonging to its +hierarchy will be throttled and are not allowed to run again until the next +period. + +A group's unused runtime is globally tracked, being refreshed with quota units +above at each period boundary. As threads consume this bandwidth it is +transferred to cpu-local "silos" on a demand basis. The amount transferred +within each of these updates is tunable and described as the "slice". + +Management +---------- +Quota and period are managed within the cpu subsystem via cgroupfs. + +cpu.cfs_quota_us: the total available run-time within a period (in microseconds) +cpu.cfs_period_us: the length of a period (in microseconds) +cpu.stat: exports throttling statistics [explained further below] + +The default values are: + cpu.cfs_period_us=100ms + cpu.cfs_quota=-1 + +A value of -1 for cpu.cfs_quota_us indicates that the group does not have any +bandwidth restriction in place, such a group is described as an unconstrained +bandwidth group. This represents the traditional work-conserving behavior for +CFS. + +Writing any (valid) positive value(s) will enact the specified bandwidth limit. +The minimum quota allowed for the quota or period is 1ms. There is also an +upper bound on the period length of 1s. Additional restrictions exist when +bandwidth limits are used in a hierarchical fashion, these are explained in +more detail below. + +Writing any negative value to cpu.cfs_quota_us will remove the bandwidth limit +and return the group to an unconstrained state once more. + +Any updates to a group's bandwidth specification will result in it becoming +unthrottled if it is in a constrained state. + +System wide settings +-------------------- +For efficiency run-time is transferred between the global pool and CPU local +"silos" in a batch fashion. This greatly reduces global accounting pressure +on large systems. The amount transferred each time such an update is required +is described as the "slice". + +This is tunable via procfs: + /proc/sys/kernel/sched_cfs_bandwidth_slice_us (default=5ms) + +Larger slice values will reduce transfer overheads, while smaller values allow +for more fine-grained consumption. + +Statistics +---------- +A group's bandwidth statistics are exported via 3 fields in cpu.stat. + +cpu.stat: +- nr_periods: Number of enforcement intervals that have elapsed. +- nr_throttled: Number of times the group has been throttled/limited. +- throttled_time: The total time duration (in nanoseconds) for which entities + of the group have been throttled. + +This interface is read-only. + +Hierarchical considerations +--------------------------- +The interface enforces that an individual entity's bandwidth is always +attainable, that is: max(c_i) <= C. However, over-subscription in the +aggregate case is explicitly allowed to enable work-conserving semantics +within a hierarchy. + e.g. \Sum (c_i) may exceed C +[ Where C is the parent's bandwidth, and c_i its children ] + + +There are two ways in which a group may become throttled: + a. it fully consumes its own quota within a period + b. a parent's quota is fully consumed within its period + +In case b) above, even though the child may have runtime remaining it will not +be allowed to until the parent's runtime is refreshed. + +Examples +-------- +1. Limit a group to 1 CPU worth of runtime. + + If period is 250ms and quota is also 250ms, the group will get + 1 CPU worth of runtime every 250ms. + + # echo 250000 > cpu.cfs_quota_us /* quota = 250ms */ + # echo 250000 > cpu.cfs_period_us /* period = 250ms */ + +2. Limit a group to 2 CPUs worth of runtime on a multi-CPU machine. + + With 500ms period and 1000ms quota, the group can get 2 CPUs worth of + runtime every 500ms. + + # echo 1000000 > cpu.cfs_quota_us /* quota = 1000ms */ + # echo 500000 > cpu.cfs_period_us /* period = 500ms */ + + The larger period here allows for increased burst capacity. + +3. Limit a group to 20% of 1 CPU. + + With 50ms period, 10ms quota will be equivalent to 20% of 1 CPU. + + # echo 10000 > cpu.cfs_quota_us /* quota = 10ms */ + # echo 50000 > cpu.cfs_period_us /* period = 50ms */ + + By using a small period here we are ensuring a consistent latency + response at the expense of burst capacity. + diff --git a/Documentation/scsi/00-INDEX b/Documentation/scsi/00-INDEX index c2e18e109858b288d29eafd9e9f7c8764a343dd8..b48ded55b555041bc638c0f003d6248217f60856 100644 --- a/Documentation/scsi/00-INDEX +++ b/Documentation/scsi/00-INDEX @@ -28,6 +28,8 @@ LICENSE.FlashPoint - Licence of the Flashpoint driver LICENSE.qla2xxx - License for QLogic Linux Fibre Channel HBA Driver firmware. +LICENSE.qla4xxx + - License for QLogic Linux iSCSI HBA Driver. Mylex.txt - info on driver for Mylex adapters NinjaSCSI.txt diff --git a/Documentation/scsi/ChangeLog.megaraid_sas b/Documentation/scsi/ChangeLog.megaraid_sas index 1b6e27ddb7f3db06fd0dc935f953a66ae4cd77f2..64adb98b181c717f763bff24109bc8bf9aff104a 100644 --- a/Documentation/scsi/ChangeLog.megaraid_sas +++ b/Documentation/scsi/ChangeLog.megaraid_sas @@ -1,3 +1,18 @@ +Release Date : Wed. Oct 5, 2011 17:00:00 PST 2010 - + (emaild-id:megaraidlinux@lsi.com) + Adam Radford +Current Version : 00.00.06.12-rc1 +Old Version : 00.00.05.40-rc1 + 1. Continue booting immediately if FW in FAULT at driver load time. + 2. Increase default cmds per lun to 256. + 3. Fix mismatch in megasas_reset_fusion() mutex lock-unlock. + 4. Remove some un-necessary code. + 5. Clear state change interrupts for Fusion/Invader. + 6. Clear FUSION_IN_RESET before enabling interrupts. + 7. Add support for MegaRAID 9360/9380 12GB/s controllers. + 8. Add multiple MSI-X vector/multiple reply queue support. + 9. Add driver workaround for PERC5/1068 kdump kernel panic. +------------------------------------------------------------------------------- Release Date : Tue. Jul 26, 2011 17:00:00 PST 2010 - (emaild-id:megaraidlinux@lsi.com) Adam Radford diff --git a/Documentation/scsi/LICENSE.qla4xxx b/Documentation/scsi/LICENSE.qla4xxx new file mode 100644 index 0000000000000000000000000000000000000000..494980e404912a861a238423e9189708549eaa66 --- /dev/null +++ b/Documentation/scsi/LICENSE.qla4xxx @@ -0,0 +1,310 @@ +Copyright (c) 2003-2011 QLogic Corporation +QLogic Linux iSCSI HBA Driver + +This program includes a device driver for Linux 3.x. +You may modify and redistribute the device driver code under the +GNU General Public License (a copy of which is attached hereto as +Exhibit A) published by the Free Software Foundation (version 2). + +REGARDLESS OF WHAT LICENSING MECHANISM IS USED OR APPLICABLE, +THIS PROGRAM IS PROVIDED BY QLOGIC CORPORATION "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 AUTHOR +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 +POSSIBILITY OF SUCH DAMAGE. + +USER ACKNOWLEDGES AND AGREES THAT USE OF THIS PROGRAM WILL NOT +CREATE OR GIVE GROUNDS FOR A LICENSE BY IMPLICATION, ESTOPPEL, OR +OTHERWISE IN ANY INTELLECTUAL PROPERTY RIGHTS (PATENT, COPYRIGHT, +TRADE SECRET, MASK WORK, OR OTHER PROPRIETARY RIGHT) EMBODIED IN +ANY OTHER QLOGIC HARDWARE OR SOFTWARE EITHER SOLELY OR IN +COMBINATION WITH THIS PROGRAM. + + +EXHIBIT A + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. diff --git a/Documentation/scsi/aic7xxx_old.txt b/Documentation/scsi/aic7xxx_old.txt index 7bd210ab45a1baacc566c551ab4f248ef51874a9..ecfc474f36a81de97dae15e49d82aa6bb2695f53 100644 --- a/Documentation/scsi/aic7xxx_old.txt +++ b/Documentation/scsi/aic7xxx_old.txt @@ -444,7 +444,7 @@ linux-1.1.x and fairly stable since linux-1.2.x, and are also in FreeBSD Kernel Compile options ------------------------------ The various kernel compile time options for this driver are now fairly - well documented in the file Documentation/Configure.help. In order to + well documented in the file drivers/scsi/Kconfig. In order to see this documentation, you need to use one of the advanced configuration programs (menuconfig and xconfig). If you are using the "make menuconfig" method of configuring your kernel, then you would simply highlight the diff --git a/Documentation/scsi/bnx2fc.txt b/Documentation/scsi/bnx2fc.txt new file mode 100644 index 0000000000000000000000000000000000000000..80823556d62f846d42af1499b314a9d85cdd4312 --- /dev/null +++ b/Documentation/scsi/bnx2fc.txt @@ -0,0 +1,75 @@ +Operating FCoE using bnx2fc +=========================== +Broadcom FCoE offload through bnx2fc is full stateful hardware offload that +cooperates with all interfaces provided by the Linux ecosystem for FC/FCoE and +SCSI controllers. As such, FCoE functionality, once enabled is largely +transparent. Devices discovered on the SAN will be registered and unregistered +automatically with the upper storage layers. + +Despite the fact that the Broadcom's FCoE offload is fully offloaded, it does +depend on the state of the network interfaces to operate. As such, the network +interface (e.g. eth0) associated with the FCoE offload initiator must be 'up'. +It is recommended that the network interfaces be configured to be brought up +automatically at boot time. + +Furthermore, the Broadcom FCoE offload solution creates VLAN interfaces to +support the VLANs that have been discovered for FCoE operation (e.g. +eth0.1001-fcoe). Do not delete or disable these interfaces or FCoE operation +will be disrupted. + +Driver Usage Model: +=================== + +1. Ensure that fcoe-utils package is installed. + +2. Configure the interfaces on which bnx2fc driver has to operate on. +Here are the steps to configure: + a. cd /etc/fcoe + b. copy cfg-ethx to cfg-eth5 if FCoE has to be enabled on eth5. + c. Repeat this for all the interfaces where FCoE has to be enabled. + d. Edit all the cfg-eth files to set "no" for DCB_REQUIRED** field, and + "yes" for AUTO_VLAN. + e. Other configuration parameters should be left as default + +3. Ensure that "bnx2fc" is in SUPPORTED_DRIVERS list in /etc/fcoe/config. + +4. Start fcoe service. (service fcoe start). If Broadcom devices are present in +the system, bnx2fc driver would automatically claim the interfaces, starts vlan +discovery and log into the targets. + +5. "Symbolic Name" in 'fcoeadm -i' output would display if bnx2fc has claimed +the interface. +Eg: +[root@bh2 ~]# fcoeadm -i + Description: NetXtreme II BCM57712 10 Gigabit Ethernet + Revision: 01 + Manufacturer: Broadcom Corporation + Serial Number: 0010186FD558 + Driver: bnx2x 1.70.00-0 + Number of Ports: 2 + + Symbolic Name: bnx2fc v1.0.5 over eth5.4 + OS Device Name: host11 + Node Name: 0x10000010186FD559 + Port Name: 0x20000010186FD559 + FabricName: 0x2001000DECB3B681 + Speed: 10 Gbit + Supported Speed: 10 Gbit + MaxFrameSize: 2048 + FC-ID (Port ID): 0x0F0377 + State: Online + +6. Verify the vlan discovery is performed by running ifconfig and notice +.-fcoe interfaces are automatically created. + +Refer to fcoeadm manpage for more information on fcoeadm operations to +create/destroy interfaces or to display lun/target information. + +NOTE: +==== +** Broadcom FCoE capable devices implement a DCBX/LLDP client on-chip. Only one +LLDP client is allowed per interface. For proper operation all host software +based DCBX/LLDP clients (e.g. lldpad) must be disabled. To disable lldpad on a +given interface, run the following command: + +lldptool set-lldp -i adminStatus=disabled diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt index 5f17d29c59b5e8e2122f5160b70e8777a11116c9..a340b18cd4ebef264e9902de658582e424893237 100644 --- a/Documentation/scsi/scsi_mid_low_api.txt +++ b/Documentation/scsi/scsi_mid_low_api.txt @@ -55,11 +55,6 @@ or in the same directory as the C source code. For example to find a url about the USB mass storage driver see the /usr/src/linux/drivers/usb/storage directory. -The Linux kernel source Documentation/DocBook/scsidrivers.tmpl file -refers to this file. With the appropriate DocBook tool-set, this permits -users to generate html, ps and pdf renderings of information within this -file (e.g. the interface functions). - Driver structure ================ Traditionally an LLD for the SCSI subsystem has been at least two files in diff --git a/Documentation/security/keys-trusted-encrypted.txt b/Documentation/security/keys-trusted-encrypted.txt index 5f50ccabfc8a45d992314774a5de80c20fa49ace..c9e4855ed3d7958f4bbbcc53025b7e8fec0c2261 100644 --- a/Documentation/security/keys-trusted-encrypted.txt +++ b/Documentation/security/keys-trusted-encrypted.txt @@ -156,4 +156,5 @@ Load an encrypted key "evm" from saved blob: Other uses for trusted and encrypted keys, such as for disk and file encryption are anticipated. In particular the new format 'ecryptfs' has been defined in in order to use encrypted keys to mount an eCryptfs filesystem. More details -about the usage can be found in the file 'Documentation/keys-ecryptfs.txt'. +about the usage can be found in the file +'Documentation/security/keys-ecryptfs.txt'. diff --git a/Documentation/serial/serial-rs485.txt b/Documentation/serial/serial-rs485.txt index a4932387bbfbc41e41ace107625b00b965cd4311..079cb3df62cf6ff9908bebe493344d1cfdd99846 100644 --- a/Documentation/serial/serial-rs485.txt +++ b/Documentation/serial/serial-rs485.txt @@ -28,6 +28,10 @@ RS485 communications. This data structure is used to set and configure RS485 parameters in the platform data and in ioctls. + The device tree can also provide RS485 boot time parameters (see [2] + for bindings). The driver is in charge of filling this data structure from + the values given by the device tree. + Any driver for devices capable of working both as RS232 and RS485 should provide at least the following ioctls: @@ -104,6 +108,9 @@ rs485conf.flags |= SER_RS485_RTS_AFTER_SEND; rs485conf.delay_rts_after_send = ...; + /* Set this flag if you want to receive data even whilst sending data */ + rs485conf.flags |= SER_RS485_RX_DURING_TX; + if (ioctl (fd, TIOCSRS485, &rs485conf) < 0) { /* Error handling. See errno. */ } @@ -118,3 +125,4 @@ 5. REFERENCES [1] include/linux/serial.h + [2] Documentation/devicetree/bindings/serial/rs485.txt diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 89757012c7ffda2d1babfd1dd9bc9d7e4d1604eb..936699e4f04b0abdf74788b66ace8ab1a16f66ff 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -886,6 +886,12 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. disable) power_save_controller - Reset HD-audio controller in power-saving mode (default = on) + align_buffer_size - Force rounding of buffer/period sizes to multiples + of 128 bytes. This is more efficient in terms of memory + access but isn't required by the HDA spec and prevents + users from specifying exact period/buffer sizes. + (default = on) + snoop - Enable/disable snooping (default = on) This module supports multiple cards and autoprobe. diff --git a/Documentation/sound/alsa/HD-Audio-Controls.txt b/Documentation/sound/alsa/HD-Audio-Controls.txt index 1482035243e677bfb21d2187e5fccb9cc01ce55c..e9621e349e1732b7d7dc75e2829b37f952f5a597 100644 --- a/Documentation/sound/alsa/HD-Audio-Controls.txt +++ b/Documentation/sound/alsa/HD-Audio-Controls.txt @@ -98,3 +98,19 @@ Conexant codecs * Auto-Mute Mode See Reatek codecs. + + +Analog codecs +-------------- + +* Channel Mode + This is an enum control to change the surround-channel setup, + appears only when the surround channels are available. + It gives the number of channels to be used, "2ch", "4ch" and "6ch". + According to the configuration, this also controls the + jack-retasking of multi-I/O jacks. + +* Independent HP + When this enum control is enabled, the headphone output is routed + from an individual stream (the third PCM such as hw:0,2) instead of + the primary stream. diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index d70c93bdcadf16a8be454581c1cb611686102cf0..4f3443230d896b92c6a5aa7b37dfd5b63e272d9b 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -29,9 +29,6 @@ ALC880 ALC260 ====== - hp HP machines - hp-3013 HP machines (3013-variant) - hp-dc7600 HP DC7600 fujitsu Fujitsu S7020 acer Acer TravelMate will Will laptops (PB V7900) @@ -46,15 +43,10 @@ ALC260 ALC262 ====== fujitsu Fujitsu Laptop - hp-bpc HP xw4400/6400/8400/9400 laptops - hp-bpc-d7000 HP BPC D7000 - hp-tc-t5735 HP Thin Client T5735 - hp-rp5700 HP RP5700 benq Benq ED8 benq-t31 Benq T31 hippo Hippo (ATI) with jack detection, Sony UX-90s hippo_1 Hippo (Benq) with jack detection - sony-assamd Sony ASSAMD toshiba-s06 Toshiba S06 toshiba-rx1 Toshiba RX1 tyan Tyan Thunder n6650W (S2915-E) @@ -66,43 +58,15 @@ ALC262 ALC267/268 ========== - quanta-il1 Quanta IL1 mini-notebook - 3stack 3-stack model - toshiba Toshiba A205 - acer Acer laptops - acer-dmic Acer laptops with digital-mic - acer-aspire Acer Aspire One - dell Dell OEM laptops (Vostro 1200) - zepto Zepto laptops - test for testing/debugging purpose, almost all controls can - adjusted. Appearing only when compiled with - $CONFIG_SND_DEBUG=y - auto auto-config reading BIOS (default) + N/A ALC269 ====== - basic Basic preset - quanta Quanta FL1 laptop-amic Laptops with analog-mic input laptop-dmic Laptops with digital-mic input - fujitsu FSC Amilo - lifebook Fujitsu Lifebook S6420 - auto auto-config reading BIOS (default) ALC662/663/272 ============== - 3stack-dig 3-stack (2-channel) with SPDIF - 3stack-6ch 3-stack (6-channel) - 3stack-6ch-dig 3-stack (6-channel) with SPDIF - 5stack-dig 5-stack with SPDIF - lenovo-101e Lenovo laptop - eeepc-p701 ASUS Eeepc P701 - eeepc-ep20 ASUS Eeepc EP20 - ecs ECS/Foxconn mobo - m51va ASUS M51VA - g71v ASUS G71V - h13 ASUS H13 - g50v ASUS G50V asus-mode1 ASUS asus-mode2 ASUS asus-mode3 ASUS @@ -111,15 +75,10 @@ ALC662/663/272 asus-mode6 ASUS asus-mode7 ASUS asus-mode8 ASUS - dell Dell with ALC272 - dell-zm1 Dell ZM1 with ALC272 - samsung-nc10 Samsung NC10 mini notebook - auto auto-config reading BIOS (default) ALC680 ====== - base Base model (ASUS NX90) - auto auto-config reading BIOS (default) + N/A ALC882/883/885/888/889 ====================== @@ -175,28 +134,11 @@ ALC882/883/885/888/889 ALC861/660 ========== - 3stack 3-jack - 3stack-dig 3-jack with SPDIF I/O - 6stack-dig 6-jack with SPDIF I/O - 3stack-660 3-jack (for ALC660) - uniwill-m31 Uniwill M31 laptop - toshiba Toshiba laptop support - asus Asus laptop support - asus-laptop ASUS F2/F3 laptops - auto auto-config reading BIOS (default) + N/A ALC861VD/660VD ============== - 3stack 3-jack - 3stack-dig 3-jack with SPDIF OUT - 6stack-dig 6-jack with SPDIF OUT - 3stack-660 3-jack (for ALC660VD) - 3stack-660-digout 3-jack with SPDIF OUT (for ALC660VD) - lenovo Lenovo 3000 C200 - dallas Dallas laptops - hp HP TX1000 - asus-v1s ASUS V1Sn - auto auto-config reading BIOS (default) + N/A CMI9880 ======= @@ -289,7 +231,6 @@ Conexant 5051 hp-dv6736 HP dv6736 hp-f700 HP Compaq Presario F700 ideapad Lenovo IdeaPad laptop - lenovo-x200 Lenovo X200 laptop toshiba Toshiba Satellite M300 Conexant 5066 diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt index c82beb0076341856ca13b1e1dd125cc440ed439c..03e2771ddeef53545357cc4bfbde29a378f9206d 100644 --- a/Documentation/sound/alsa/HD-Audio.txt +++ b/Documentation/sound/alsa/HD-Audio.txt @@ -447,7 +447,10 @@ The file needs to have a line `[codec]`. The next line should contain three numbers indicating the codec vendor-id (0x12345678 in the example), the codec subsystem-id (0xabcd1234) and the address (2) of the codec. The rest patch entries are applied to this specified codec -until another codec entry is given. +until another codec entry is given. Passing 0 or a negative number to +the first or the second value will make the check of the corresponding +field be skipped. It'll be useful for really broken devices that don't +initialize SSID properly. The `[model]` line allows to change the model name of the each codec. In the example above, it will be changed to model=auto. @@ -491,7 +494,7 @@ Also, the codec chip name can be rewritten via `[chip_name]` line. The hd-audio driver reads the file via request_firmware(). Thus, a patch file has to be located on the appropriate firmware path, typically, /lib/firmware. For example, when you pass the option -`patch=hda-init.fw`, the file /lib/firmware/hda-init-fw must be +`patch=hda-init.fw`, the file /lib/firmware/hda-init.fw must be present. The patch module option is specific to each card instance, and you @@ -524,6 +527,54 @@ power-saving. See /sys/module/snd_hda_intel/parameters/power_save to check the current value. If it's non-zero, the feature is turned on. +Tracepoints +~~~~~~~~~~~ +The hd-audio driver gives a few basic tracepoints. +`hda:hda_send_cmd` traces each CORB write while `hda:hda_get_response` +traces the response from RIRB (only when read from the codec driver). +`hda:hda_bus_reset` traces the bus-reset due to fatal error, etc, +`hda:hda_unsol_event` traces the unsolicited events, and +`hda:hda_power_down` and `hda:hda_power_up` trace the power down/up +via power-saving behavior. + +Enabling all tracepoints can be done like +------------------------------------------------------------------------ + # echo 1 > /sys/kernel/debug/tracing/events/hda/enable +------------------------------------------------------------------------ +then after some commands, you can traces from +/sys/kernel/debug/tracing/trace file. For example, when you want to +trace what codec command is sent, enable the tracepoint like: +------------------------------------------------------------------------ + # cat /sys/kernel/debug/tracing/trace + # tracer: nop + # + # TASK-PID CPU# TIMESTAMP FUNCTION + # | | | | | + <...>-7807 [002] 105147.774889: hda_send_cmd: [0:0] val=e3a019 + <...>-7807 [002] 105147.774893: hda_send_cmd: [0:0] val=e39019 + <...>-7807 [002] 105147.999542: hda_send_cmd: [0:0] val=e3a01a + <...>-7807 [002] 105147.999543: hda_send_cmd: [0:0] val=e3901a + <...>-26764 [001] 349222.837143: hda_send_cmd: [0:0] val=e3a019 + <...>-26764 [001] 349222.837148: hda_send_cmd: [0:0] val=e39019 + <...>-26764 [001] 349223.058539: hda_send_cmd: [0:0] val=e3a01a + <...>-26764 [001] 349223.058541: hda_send_cmd: [0:0] val=e3901a +------------------------------------------------------------------------ +Here `[0:0]` indicates the card number and the codec address, and +`val` shows the value sent to the codec, respectively. The value is +a packed value, and you can decode it via hda-decode-verb program +included in hda-emu package below. For example, the value e3a019 is +to set the left output-amp value to 25. +------------------------------------------------------------------------ + % hda-decode-verb 0xe3a019 + raw value = 0x00e3a019 + cid = 0, nid = 0x0e, verb = 0x3a0, parm = 0x19 + raw value: verb = 0x3a0, parm = 0x19 + verbname = set_amp_gain_mute + amp raw val = 0xa019 + output, left, idx=0, mute=0, val=25 +------------------------------------------------------------------------ + + Development Tree ~~~~~~~~~~~~~~~~ The latest development codes for HD-audio are found on sound git tree: diff --git a/Documentation/sound/oss/PAS16 b/Documentation/sound/oss/PAS16 index 951b3dce51b4da543b2d67824b0ffdee2f796c7d..3dca4b75988e77cc0da179abd42969165975e37c 100644 --- a/Documentation/sound/oss/PAS16 +++ b/Documentation/sound/oss/PAS16 @@ -60,8 +60,7 @@ With PAS16 you can use two audio device files at the same time. /dev/dsp (and The new stuff for 2.3.99 and later ============================================================================ -The following configuration options from Documentation/Configure.help -are relevant to configuring the PAS16: +The following configuration options are relevant to configuring the PAS16: Sound card support CONFIG_SOUND diff --git a/Documentation/spi/pxa2xx b/Documentation/spi/pxa2xx index 00511e08db787145805a8510c0035a34c77eec17..3352f97430e4e1132f41b19dd2f00ce93b3846e4 100644 --- a/Documentation/spi/pxa2xx +++ b/Documentation/spi/pxa2xx @@ -2,7 +2,7 @@ PXA2xx SPI on SSP driver HOWTO =================================================== This a mini howto on the pxa2xx_spi driver. The driver turns a PXA2xx synchronous serial port into a SPI master controller -(see Documentation/spi/spi_summary). The driver has the following features +(see Documentation/spi/spi-summary). The driver has the following features - Support for any PXA2xx SSP - SSP PIO and SSP DMA data transfers. @@ -85,7 +85,7 @@ Declaring Slave Devices ----------------------- Typically each SPI slave (chip) is defined in the arch/.../mach-*/board-*.c using the "spi_board_info" structure found in "linux/spi/spi.h". See -"Documentation/spi/spi_summary" for additional information. +"Documentation/spi/spi-summary" for additional information. Each slave device attached to the PXA must provide slave specific configuration information via the structure "pxa2xx_spi_chip" found in diff --git a/Documentation/stable_kernel_rules.txt b/Documentation/stable_kernel_rules.txt index e213f45cf9d7505c9c9e1fbd088eb91cd83292f4..21fd05c28e738e146b313081bbd4294687ddabdf 100644 --- a/Documentation/stable_kernel_rules.txt +++ b/Documentation/stable_kernel_rules.txt @@ -24,10 +24,10 @@ Rules on what kind of patches are accepted, and which ones are not, into the Procedure for submitting patches to the -stable tree: - Send the patch, after verifying that it follows the above rules, to - stable@kernel.org. You must note the upstream commit ID in the changelog - of your submission. + stable@vger.kernel.org. You must note the upstream commit ID in the + changelog of your submission. - To have the patch automatically included in the stable tree, add the tag - Cc: stable@kernel.org + Cc: stable@vger.kernel.org in the sign-off area. Once the patch is merged it will be applied to the stable tree without anything else needing to be done by the author or subsystem maintainer. @@ -35,10 +35,10 @@ Procedure for submitting patches to the -stable tree: cherry-picked than this can be specified in the following format in the sign-off area: - Cc: # .32.x: a1f84a3: sched: Check for idle - Cc: # .32.x: 1b9508f: sched: Rate-limit newidle - Cc: # .32.x: fd21073: sched: Fix affinity logic - Cc: # .32.x + Cc: # .32.x: a1f84a3: sched: Check for idle + Cc: # .32.x: 1b9508f: sched: Rate-limit newidle + Cc: # .32.x: fd21073: sched: Fix affinity logic + Cc: # .32.x Signed-off-by: Ingo Molnar The tag sequence has the meaning of: diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt index 704e474a93df8539e093aa3569bb889faa1adb70..1f2463671a1a4d59d0981f0b877c2a1246da82db 100644 --- a/Documentation/sysctl/kernel.txt +++ b/Documentation/sysctl/kernel.txt @@ -24,6 +24,7 @@ show up in /proc/sys/kernel: - bootloader_type [ X86 only ] - bootloader_version [ X86 only ] - callhome [ S390 only ] +- cap_last_cap - core_pattern - core_pipe_limit - core_uses_pid @@ -155,6 +156,13 @@ on has a service contract with IBM. ============================================================== +cap_last_cap + +Highest valid capability of the running kernel. Exports +CAP_LAST_CAP from the kernel. + +============================================================== + core_pattern: core_pattern is used to specify a core dumpfile pattern name. diff --git a/Documentation/timers/highres.txt b/Documentation/timers/highres.txt index 21332233cef16a157b95519640e356beadf2eeee..e8789976e77c30d1d5235d19cb1d613e52d71067 100644 --- a/Documentation/timers/highres.txt +++ b/Documentation/timers/highres.txt @@ -30,7 +30,7 @@ hrtimer base infrastructure --------------------------- The hrtimer base infrastructure was merged into the 2.6.16 kernel. Details of -the base implementation are covered in Documentation/hrtimers/hrtimer.txt. See +the base implementation are covered in Documentation/timers/hrtimers.txt. See also figure #2 (OLS slides p. 15) The main differences to the timer wheel, which holds the armed timer_list type diff --git a/Documentation/trace/postprocess/trace-vmscan-postprocess.pl b/Documentation/trace/postprocess/trace-vmscan-postprocess.pl index 12cecc83cd91c658c71524bba59762b83f810829..4a37c4759cd231f72a8b5f253deec9fdec334886 100644 --- a/Documentation/trace/postprocess/trace-vmscan-postprocess.pl +++ b/Documentation/trace/postprocess/trace-vmscan-postprocess.pl @@ -379,10 +379,10 @@ EVENT_PROCESS: # To closer match vmstat scanning statistics, only count isolate_both # and isolate_inactive as scanning. isolate_active is rotation - # isolate_inactive == 0 - # isolate_active == 1 - # isolate_both == 2 - if ($isolate_mode != 1) { + # isolate_inactive == 1 + # isolate_active == 2 + # isolate_both == 3 + if ($isolate_mode != 2) { $perprocesspid{$process_pid}->{HIGH_NR_SCANNED} += $nr_scanned; } $perprocesspid{$process_pid}->{HIGH_NR_CONTIG_DIRTY} += $nr_contig_dirty; diff --git a/Documentation/usb/dma.txt b/Documentation/usb/dma.txt index 84ef865237db3069e835dbbdba7f562489a204f6..444651e70d9552f2782eb9cd0b22096a93233672 100644 --- a/Documentation/usb/dma.txt +++ b/Documentation/usb/dma.txt @@ -7,7 +7,7 @@ API OVERVIEW The big picture is that USB drivers can continue to ignore most DMA issues, though they still must provide DMA-ready buffers (see -Documentation/PCI/PCI-DMA-mapping.txt). That's how they've worked through +Documentation/DMA-API-HOWTO.txt). That's how they've worked through the 2.4 (and earlier) kernels. OR: they can now be DMA-aware. @@ -57,7 +57,7 @@ and effects like cache-trashing can impose subtle penalties. force a consistent memory access ordering by using memory barriers. It's not using a streaming DMA mapping, so it's good for small transfers on systems where the I/O would otherwise thrash an IOMMU mapping. (See - Documentation/PCI/PCI-DMA-mapping.txt for definitions of "coherent" and + Documentation/DMA-API-HOWTO.txt for definitions of "coherent" and "streaming" DMA mappings.) Asking for 1/Nth of a page (as well as asking for N pages) is reasonably @@ -88,7 +88,7 @@ WORKING WITH EXISTING BUFFERS Existing buffers aren't usable for DMA without first being mapped into the DMA address space of the device. However, most buffers passed to your driver can safely be used with such DMA mapping. (See the first section -of Documentation/PCI/PCI-DMA-mapping.txt, titled "What memory is DMA-able?") +of Documentation/DMA-API-HOWTO.txt, titled "What memory is DMA-able?") - When you're using scatterlists, you can map everything at once. On some systems, this kicks in an IOMMU and turns the scatterlists into single diff --git a/Documentation/usb/dwc3.txt b/Documentation/usb/dwc3.txt new file mode 100644 index 0000000000000000000000000000000000000000..7b590edae14579b09512deb3116231f24213ea82 --- /dev/null +++ b/Documentation/usb/dwc3.txt @@ -0,0 +1,45 @@ + + TODO +~~~~~~ +Please pick something while reading :) + +- Convert interrupt handler to per-ep-thread-irq + + As it turns out some DWC3-commands ~1ms to complete. Currently we spin + until the command completes which is bad. + + Implementation idea: + - dwc core implements a demultiplexing irq chip for interrupts per + endpoint. The interrupt numbers are allocated during probe and belong + to the device. If MSI provides per-endpoint interrupt this dummy + interrupt chip can be replaced with "real" interrupts. + - interrupts are requested / allocated on usb_ep_enable() and removed on + usb_ep_disable(). Worst case are 32 interrupts, the lower limit is two + for ep0/1. + - dwc3_send_gadget_ep_cmd() will sleep in wait_for_completion_timeout() + until the command completes. + - the interrupt handler is split into the following pieces: + - primary handler of the device + goes through every event and calls generic_handle_irq() for event + it. On return from generic_handle_irq() in acknowledges the event + counter so interrupt goes away (eventually). + + - threaded handler of the device + none + + - primary handler of the EP-interrupt + reads the event and tries to process it. Everything that requries + sleeping is handed over to the Thread. The event is saved in an + per-endpoint data-structure. + We probably have to pay attention not to process events once we + handed something to thread so we don't process event X prio Y + where X > Y. + + - threaded handler of the EP-interrupt + handles the remaining EP work which might sleep such as waiting + for command completion. + + Latency: + There should be no increase in latency since the interrupt-thread has a + high priority and will be run before an average task in user land + (except the user changed priorities). diff --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt index c9ffa9ced7eec964e47c2513584f9041a6fb9c7e..12511c98cc4faecaf17f31db16f1db347936dad2 100644 --- a/Documentation/usb/power-management.txt +++ b/Documentation/usb/power-management.txt @@ -439,10 +439,10 @@ cause autosuspends to fail with -EBUSY if the driver needs to use the device. External suspend calls should never be allowed to fail in this way, -only autosuspend calls. The driver can tell them apart by checking -the PM_EVENT_AUTO bit in the message.event argument to the suspend -method; this bit will be set for internal PM events (autosuspend) and -clear for external PM events. +only autosuspend calls. The driver can tell them apart by applying +the PMSG_IS_AUTO() macro to the message argument to the suspend +method; it will return True for internal PM events (autosuspend) and +False for external PM events. Mutual exclusion @@ -487,3 +487,29 @@ succeed, it may still remain active and thus cause the system to resume as soon as the system suspend is complete. Or the remote wakeup may fail and get lost. Which outcome occurs depends on timing and on the hardware and firmware design. + + + xHCI hardware link PM + --------------------- + +xHCI host controller provides hardware link power management to usb2.0 +(xHCI 1.0 feature) and usb3.0 devices which support link PM. By +enabling hardware LPM, the host can automatically put the device into +lower power state(L1 for usb2.0 devices, or U1/U2 for usb3.0 devices), +which state device can enter and resume very quickly. + +The user interface for controlling USB2 hardware LPM is located in the +power/ subdirectory of each USB device's sysfs directory, that is, in +/sys/bus/usb/devices/.../power/ where "..." is the device's ID. The +relevant attribute files is usb2_hardware_lpm. + + power/usb2_hardware_lpm + + When a USB2 device which support LPM is plugged to a + xHCI host root hub which support software LPM, the + host will run a software LPM test for it; if the device + enters L1 state and resume successfully and the host + supports USB2 hardware LPM, this file will show up and + driver will enable hardware LPM for the device. You + can write y/Y/1 or n/N/0 to the file to enable/disable + USB2 hardware LPM manually. This is for test purpose mainly. diff --git a/drivers/staging/tm6000/CARDLIST b/Documentation/video4linux/CARDLIST.tm6000 similarity index 100% rename from drivers/staging/tm6000/CARDLIST rename to Documentation/video4linux/CARDLIST.tm6000 diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index 5bfa9a777d26c5696ee10b5bef0e23d1baea8190..b15e29f3112113416f238cb686047430caf17eeb 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt @@ -8,6 +8,7 @@ xxxx vend:prod ---- spca501 0000:0000 MystFromOri Unknown Camera spca508 0130:0130 Clone Digital Webcam 11043 +zc3xx 03f0:1b07 HP Premium Starter Cam m5602 0402:5602 ALi Video Camera Controller spca501 040a:0002 Kodak DVC-325 spca500 040a:0300 Kodak EZ200 @@ -190,6 +191,7 @@ ov519 05a9:0519 OV519 Microphone ov519 05a9:0530 OmniVision ov519 05a9:2800 OmniVision SuperCAM ov519 05a9:4519 Webcam Classic +ov534_9 05a9:8065 OmniVision test kit ov538+ov9712 ov519 05a9:8519 OmniVision ov519 05a9:a511 D-Link USB Digital Video Camera ov519 05a9:a518 D-Link DSB-C310 Webcam @@ -199,6 +201,8 @@ gl860 05e3:0503 Genesys Logic PC Camera gl860 05e3:f191 Genesys Logic PC Camera spca561 060b:a001 Maxell Compact Pc PM3 zc3xx 0698:2003 CTX M730V built in +topro 06a2:0003 TP6800 PC Camera, CmoX CX0342 webcam +topro 06a2:6810 Creative Qmax nw80x 06a5:0000 Typhoon Webcam 100 USB nw80x 06a5:d001 Divio based webcams nw80x 06a5:d800 Divio Chicony TwinkleCam, Trust SpaceCam diff --git a/Documentation/video4linux/omap3isp.txt b/Documentation/video4linux/omap3isp.txt index 69be2c782b989b5616596be15c70b3dd42c4e669..5dd1439b61fd512b94b3404f959e824ab3816f4d 100644 --- a/Documentation/video4linux/omap3isp.txt +++ b/Documentation/video4linux/omap3isp.txt @@ -70,10 +70,11 @@ Events The OMAP 3 ISP driver does support the V4L2 event interface on CCDC and statistics (AEWB, AF and histogram) subdevs. -The CCDC subdev produces V4L2_EVENT_OMAP3ISP_HS_VS type event on HS_VS -interrupt which is used to signal frame start. The event is triggered exactly -when the reception of the first line of the frame starts in the CCDC module. -The event can be subscribed on the CCDC subdev. +The CCDC subdev produces V4L2_EVENT_FRAME_SYNC type event on HS_VS +interrupt which is used to signal frame start. Earlier version of this +driver used V4L2_EVENT_OMAP3ISP_HS_VS for this purpose. The event is +triggered exactly when the reception of the first line of the frame starts +in the CCDC module. The event can be subscribed on the CCDC subdev. (When using parallel interface one must pay account to correct configuration of the VS signal polarity. This is automatically correct when using the serial diff --git a/Documentation/video4linux/v4l2-controls.txt b/Documentation/video4linux/v4l2-controls.txt index 9346fc8cbf2b2323e205f1f8669fd626cfc1047a..26aa0573933e8f5f970f7f18b3f53f0afd37eb6d 100644 --- a/Documentation/video4linux/v4l2-controls.txt +++ b/Documentation/video4linux/v4l2-controls.txt @@ -285,11 +285,11 @@ implement g_volatile_ctrl like this: Note that you use the 'new value' union as well in g_volatile_ctrl. In general controls that need to implement g_volatile_ctrl are read-only controls. -To mark a control as volatile you have to set the is_volatile flag: +To mark a control as volatile you have to set V4L2_CTRL_FLAG_VOLATILE: ctrl = v4l2_ctrl_new_std(&sd->ctrl_handler, ...); if (ctrl) - ctrl->is_volatile = 1; + ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; For try/s_ctrl the new values (i.e. as passed by the user) are filled in and you can modify them in try_ctrl or set them in s_ctrl. The 'cur' union @@ -367,8 +367,7 @@ Driver specific controls can be created using v4l2_ctrl_new_custom(): The last argument is the priv pointer which can be set to driver-specific private data. -The v4l2_ctrl_config struct also has fields to set the is_private and is_volatile -flags. +The v4l2_ctrl_config struct also has a field to set the is_private flag. If the name field is not set, then the framework will assume this is a standard control and will fill in the name, type and flags fields accordingly. @@ -496,18 +495,20 @@ Handling autogain/gain-type Controls with Auto Clusters A common type of control cluster is one that handles 'auto-foo/foo'-type controls. Typical examples are autogain/gain, autoexposure/exposure, -autowhitebalance/red balance/blue balance. In all cases you have one controls +autowhitebalance/red balance/blue balance. In all cases you have one control that determines whether another control is handled automatically by the hardware, or whether it is under manual control from the user. If the cluster is in automatic mode, then the manual controls should be -marked inactive. When the volatile controls are read the g_volatile_ctrl -operation should return the value that the hardware's automatic mode set up -automatically. +marked inactive and volatile. When the volatile controls are read the +g_volatile_ctrl operation should return the value that the hardware's automatic +mode set up automatically. If the cluster is put in manual mode, then the manual controls should become -active again and the is_volatile flag should be ignored (so g_volatile_ctrl is -no longer called while in manual mode). +active again and the volatile flag is cleared (so g_volatile_ctrl is no longer +called while in manual mode). In addition just before switching to manual mode +the current values as determined by the auto mode are copied as the new manual +values. Finally the V4L2_CTRL_FLAG_UPDATE should be set for the auto control since changing that control affects the control flags of the manual controls. @@ -520,7 +521,11 @@ void v4l2_ctrl_auto_cluster(unsigned ncontrols, struct v4l2_ctrl **controls, The first two arguments are identical to v4l2_ctrl_cluster. The third argument tells the framework which value switches the cluster into manual mode. The -last argument will optionally set the is_volatile flag for the non-auto controls. +last argument will optionally set V4L2_CTRL_FLAG_VOLATILE for the non-auto controls. +If it is false, then the manual controls are never volatile. You would typically +use that if the hardware does not give you the option to read back to values as +determined by the auto mode (e.g. if autogain is on, the hardware doesn't allow +you to obtain the current gain value). The first control of the cluster is assumed to be the 'auto' control. @@ -681,16 +686,6 @@ if there are no controls at all. count if nothing was done yet. If it is less than count then only the controls up to error_idx-1 were successfully applied. -3) When attempting to read a button control the framework will return -EACCES -instead of -EINVAL as stated in the spec. It seems to make more sense since -button controls are write-only controls. - -4) Attempting to write to a read-only control will return -EACCES instead of --EINVAL as the spec says. - -5) The spec does not mention what should happen when you try to set/get a -control class controls. The framework will return -EACCES. - Proposals for Extensions ======================== @@ -703,9 +698,3 @@ decimal. Useful for e.g. video_mute_yuv. 2) It is possible to mark in the controls array which controls have been successfully written and which failed by for example adding a bit to the control ID. Not sure if it is worth the effort, though. - -3) Trying to set volatile inactive controls should result in -EACCESS. - -4) Add a new flag to mark volatile controls. Any application that wants -to store the state of the controls can then skip volatile inactive controls. -Currently it is not possible to detect such controls. diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index b0e4b9cd6a663a412ab9772a220ea8447aa349dd..7945b0bd35e2ad50d7561ffa88a428c21175b50b 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -175,10 +175,30 @@ Parameters: vcpu id (apic id on x86) Returns: vcpu fd on success, -1 on error This API adds a vcpu to a virtual machine. The vcpu id is a small integer -in the range [0, max_vcpus). You can use KVM_CAP_NR_VCPUS of the -KVM_CHECK_EXTENSION ioctl() to determine the value for max_vcpus at run-time. +in the range [0, max_vcpus). + +The recommended max_vcpus value can be retrieved using the KVM_CAP_NR_VCPUS of +the KVM_CHECK_EXTENSION ioctl() at run-time. +The maximum possible value for max_vcpus can be retrieved using the +KVM_CAP_MAX_VCPUS of the KVM_CHECK_EXTENSION ioctl() at run-time. + If the KVM_CAP_NR_VCPUS does not exist, you should assume that max_vcpus is 4 cpus max. +If the KVM_CAP_MAX_VCPUS does not exist, you should assume that max_vcpus is +same as the value returned from KVM_CAP_NR_VCPUS. + +On powerpc using book3s_hv mode, the vcpus are mapped onto virtual +threads in one or more virtual CPU cores. (This is because the +hardware requires all the hardware threads in a CPU core to be in the +same partition.) The KVM_CAP_PPC_SMT capability indicates the number +of vcpus per virtual core (vcore). The vcore id is obtained by +dividing the vcpu id by the number of vcpus per vcore. The vcpus in a +given vcore will always be in the same physical core as each other +(though that might be a different physical core from time to time). +Userspace can control the threading (SMT) mode of the guest by its +allocation of vcpu ids. For example, if userspace wants +single-threaded guest vcpus, it should make all vcpu ids be a multiple +of the number of vcpus per vcore. On powerpc using book3s_hv mode, the vcpus are mapped onto virtual threads in one or more virtual CPU cores. (This is because the @@ -1633,3 +1653,50 @@ developer registration required to access it). char padding[256]; }; }; + +6. Capabilities that can be enabled + +There are certain capabilities that change the behavior of the virtual CPU when +enabled. To enable them, please see section 4.37. Below you can find a list of +capabilities and what their effect on the vCPU is when enabling them. + +The following information is provided along with the description: + + Architectures: which instruction set architectures provide this ioctl. + x86 includes both i386 and x86_64. + + Parameters: what parameters are accepted by the capability. + + Returns: the return value. General error numbers (EBADF, ENOMEM, EINVAL) + are not detailed, but errors with specific meanings are. + +6.1 KVM_CAP_PPC_OSI + +Architectures: ppc +Parameters: none +Returns: 0 on success; -1 on error + +This capability enables interception of OSI hypercalls that otherwise would +be treated as normal system calls to be injected into the guest. OSI hypercalls +were invented by Mac-on-Linux to have a standardized communication mechanism +between the guest and the host. + +When this capability is enabled, KVM_EXIT_OSI can occur. + +6.2 KVM_CAP_PPC_PAPR + +Architectures: ppc +Parameters: none +Returns: 0 on success; -1 on error + +This capability enables interception of PAPR hypercalls. PAPR hypercalls are +done using the hypercall instruction "sc 1". + +It also sets the guest privilege level to "supervisor" mode. Usually the guest +runs in "hypervisor" privilege mode with a few missing features. + +In addition to the above, it changes the semantics of SDR1. In this mode, the +HTAB address part of SDR1 contains an HVA instead of a GPA, as PAPR keeps the +HTAB invisible to the guest. + +When this capability is enabled, KVM_EXIT_PAPR_HCALL can occur. diff --git a/Documentation/virtual/lguest/lguest.c b/Documentation/virtual/lguest/lguest.c index d928c134dee66953f0b7f163a8e3633ac95e3747..c095d79cae73d1acf8d2ae9991661be35be008bd 100644 --- a/Documentation/virtual/lguest/lguest.c +++ b/Documentation/virtual/lguest/lguest.c @@ -436,7 +436,7 @@ static unsigned long load_bzimage(int fd) /* * Go back to the start of the file and read the header. It should be - * a Linux boot header (see Documentation/x86/i386/boot.txt) + * a Linux boot header (see Documentation/x86/boot.txt) */ lseek(fd, 0, SEEK_SET); read(fd, &boot, sizeof(boot)); diff --git a/Documentation/vm/00-INDEX b/Documentation/vm/00-INDEX index dca82d7c83d8e7a74063ece424f2d82d48b4dce6..5481c8ba34122df7d89ccc16f732174b987c699a 100644 --- a/Documentation/vm/00-INDEX +++ b/Documentation/vm/00-INDEX @@ -30,8 +30,6 @@ page_migration - description of page migration in NUMA systems. pagemap.txt - pagemap, from the userspace perspective -slabinfo.c - - source code for a tool to get reports about slabs. slub.txt - a short users guide for SLUB. unevictable-lru.txt diff --git a/Documentation/vm/numa b/Documentation/vm/numa index a200a386429d568776c3737e860b0b2c81672c52..ade01274212d9b4ea8fedfef459d2de670a7ede5 100644 --- a/Documentation/vm/numa +++ b/Documentation/vm/numa @@ -109,11 +109,11 @@ to improve NUMA locality using various CPU affinity command line interfaces, such as taskset(1) and numactl(1), and program interfaces such as sched_setaffinity(2). Further, one can modify the kernel's default local allocation behavior using Linux NUMA memory policy. -[see Documentation/vm/numa_memory_policy.] +[see Documentation/vm/numa_memory_policy.txt.] System administrators can restrict the CPUs and nodes' memories that a non- privileged user can specify in the scheduling or NUMA commands and functions -using control groups and CPUsets. [see Documentation/cgroups/CPUsets.txt] +using control groups and CPUsets. [see Documentation/cgroups/cpusets.txt] On architectures that do not hide memoryless nodes, Linux will include only zones [nodes] with memory in the zonelists. This means that for a memoryless diff --git a/Documentation/vm/slub.txt b/Documentation/vm/slub.txt index 07375e73981a8747f1432213691a4187ccf6544a..f464f47bc60dacd77fecc7797dfe658708acb41e 100644 --- a/Documentation/vm/slub.txt +++ b/Documentation/vm/slub.txt @@ -17,7 +17,7 @@ data and perform operation on the slabs. By default slabinfo only lists slabs that have data in them. See "slabinfo -h" for more options when running the command. slabinfo can be compiled with -gcc -o slabinfo Documentation/vm/slabinfo.c +gcc -o slabinfo tools/slub/slabinfo.c Some of the modes of operation of slabinfo require that slub debugging be enabled on the command line. F.e. no tracking information will be diff --git a/Documentation/x86/entry_64.txt b/Documentation/x86/entry_64.txt index 7869f14d055cc3899315defbef14320c6314b725..bc7226ef5055c4c3bec4b7a270f8260449fe705c 100644 --- a/Documentation/x86/entry_64.txt +++ b/Documentation/x86/entry_64.txt @@ -27,9 +27,6 @@ Some of these entries are: magically-generated functions that make their way to do_IRQ with the interrupt number as a parameter. - - emulate_vsyscall: int 0xcc, a special non-ABI entry used by - vsyscall emulation. - - APIC interrupts: Various special-purpose interrupts for things like TLB shootdown. diff --git a/Documentation/zh_CN/SubmitChecklist b/Documentation/zh_CN/SubmitChecklist deleted file mode 100644 index 4c741d6bc048d2dbc86790ba754b492b134f860a..0000000000000000000000000000000000000000 --- a/Documentation/zh_CN/SubmitChecklist +++ /dev/null @@ -1,109 +0,0 @@ -Chinese translated version of Documentation/SubmitChecklist - -If you have any comment or update to the content, please contact the -original document maintainer directly. However, if you have a problem -communicating in English you can also ask the Chinese maintainer for -help. Contact the Chinese maintainer if this translation is outdated -or if there is a problem with the translation. - -Chinese maintainer: Harry Wei ---------------------------------------------------------------------- -Documentation/SubmitChecklist µÄÖÐÎÄ·­Òë - -Èç¹ûÏëÆÀÂÛ»ò¸üб¾ÎĵÄÄÚÈÝ£¬ÇëÖ±½ÓÁªÏµÔ­ÎĵµµÄά»¤Õß¡£Èç¹ûÄãʹÓÃÓ¢ÎÄ -½»Á÷ÓÐÀ§ÄѵĻ°£¬Ò²¿ÉÒÔÏòÖÐÎÄ°æά»¤ÕßÇóÖú¡£Èç¹û±¾·­Òë¸üв»¼°Ê±»òÕß·­ -Òë´æÔÚÎÊÌ⣬ÇëÁªÏµÖÐÎÄ°æά»¤Õß¡£ - -ÖÐÎÄ°æά»¤Õߣº ¼ÖÍþÍþ Harry Wei -ÖÐÎÄ°æ·­ÒëÕߣº ¼ÖÍþÍþ Harry Wei -ÖÐÎÄ°æУÒëÕߣº ¼ÖÍþÍþ Harry Wei - - -ÒÔÏÂΪÕýÎÄ ---------------------------------------------------------------------- -LinuxÄÚºËÌá½»Çåµ¥ -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -ÕâÀïÓÐһЩÄں˿ª·¢ÕßÓ¦¸Ã×öµÄ»ù±¾ÊÂÇ飬Èç¹ûËûÃÇÏë¿´µ½×Ô¼ºµÄÄں˲¹¶¡Ìá½» -±»½ÓÊܵĸü¿ì¡£ - -ÕâЩ¶¼Êdz¬³öDocumentation/SubmittingPatchesÎĵµÀïËùÌṩµÄÒÔ¼°ÆäËû -¹ØÓÚÌá½»LinuxÄں˲¹¶¡µÄ˵Ã÷¡£ - -1£ºÈç¹ûÄãʹÓÃÁËÒ»¸ö¹¦ÄÜÄÇô¾Í#include¶¨Òå/ÉùÃ÷ÄǸö¹¦ÄܵÄÄǸöÎļþ¡£ - ²»ÒªÒÀ¿¿ÆäËû¼ä½ÓÒýÈ붨Òå/ÉùÃ÷ÄǸö¹¦ÄܵÄÍ·Îļþ¡£ - -2£º¹¹½¨¼ò½àÊÊÓûòÕ߸ü¸ÄCONFIGÑ¡Ïî =y£¬=m£¬»òÕß=n¡£ - ²»ÒªÓбàÒ뾯¸æ/´íÎó£¬ ²»ÒªÓÐÁ´½Ó¾¯¸æ/´íÎó¡£ - -2b£ºÍ¨¹ý allnoconfig, allmodconfig - -2c£ºµ±Ê¹Óà 0=builddir ³É¹¦µØ¹¹½¨ - -3£ºÍ¨¹ýʹÓñ¾µØ½»²æ±àÒ빤¾ß»òÕßÆäËûһЩ¹¹½¨²úËù£¬ÔÚ¶àCPU¿ò¼ÜÉϹ¹½¨¡£ - -4£ºppc64 ÊÇÒ»¸öºÜºÃµÄ¼ì²é½»²æ±àÒëµÄ¿ò¼Ü£¬ÒòΪËüÍùÍù°Ñ¡®unsigned long¡¯ - µ±64λֵÀ´Ê¹Óᣠ- -5£º°´ÕÕDocumentation/CodingStyleÎļþÀïµÄÏêϸÃèÊö£¬¼ì²éÄã²¹¶¡µÄÕûÌå·ç¸ñ¡£ - ʹÓò¹¶¡·ç¸ñ¼ì²éËöËéµÄÎ¥¹æ(scripts/checkpatch.pl)£¬ÉóºËÔ±ÓÅÏÈÌá½»¡£ - ÄãÓ¦¸Ãµ÷ÕûÒÅÁôÔÚÄã²¹¶¡ÖеÄËùÓÐÎ¥¹æ¡£ - -6£ºÈκθüлòÕ߸Ķ¯CONFIGÑ¡Ï²»ÄÜ´òÂÒÅäÖò˵¥¡£ - -7£ºËùÓеÄKconfigÑ¡Ïî¸üж¼ÒªÓÐ˵Ã÷ÎÄ×Ö¡£ - -8£ºÒѾ­ÈÏÕæµØ×ܽáÁËÏà¹ØµÄKconfig×éºÏ¡£ÕâÊǺÜÄÑͨ¹ý²âÊÔ×öºÃµÄ--ÄÔÁ¦ÔÚÕâÀïϽµ¡£ - -9£º¼ì²é¾ßÓмò½àÐÔ¡£ - -10£ºÊ¹ÓÃ'make checkstack'ºÍ'make namespacecheck'¼ì²é£¬È»ºóÐÞ¸ÄËùÕÒµ½µÄÎÊÌâ¡£ - ×¢Ò⣺¶ÑÕ»¼ì²é²»»áÃ÷È·µØ³öÏÖÎÊÌ⣬µ«ÊÇÈκεÄÒ»¸öº¯ÊýÔÚ¶ÑÕ»ÉÏʹÓöàÓÚ512×Ö½Ú - ¶¼Òª×¼±¸Ð޸ġ£ - -11£º°üº¬kernel-docµ½È«¾ÖÄÚºËAPIsÎļþ¡££¨²»ÒªÇó¾²Ì¬µÄº¯Êý£¬µ«ÊÇ°üº¬Ò²ÎÞËùν¡££© - ʹÓÃ'make htmldocs'»òÕß'make mandocs'À´¼ì²ékernel-doc£¬È»ºóÐÞ¸ÄÈκΠ- ·¢ÏÖµÄÎÊÌâ¡£ - -12£ºÒѾ­Í¨¹ýCONFIG_PREEMPT, CONFIG_DEBUG_PREEMPT, - CONFIG_DEBUG_SLAB, CONFIG_DEBUG_PAGEALLOC, CONFIG_DEBUG_MUTEXES, - CONFIG_DEBUG_SPINLOCK, CONFIG_DEBUG_ATOMIC_SLEEP²âÊÔ£¬²¢ÇÒͬʱ¶¼ - ʹÄÜ¡£ - -13£ºÒѾ­¶¼¹¹½¨²¢ÇÒʹÓûòÕß²»Ê¹Óà CONFIG_SMP ºÍ CONFIG_PREEMPT²âÊÔÖ´ÐÐʱ¼ä¡£ - -14£ºÈç¹û²¹¶¡Ó°ÏìIO/Disk£¬µÈµÈ£ºÒѾ­Í¨¹ýʹÓûòÕß²»Ê¹Óà CONFIG_LBDAF ²âÊÔ¡£ - -15£ºËùÓеÄcodepathsÒѾ­ÐÐʹËùÓÐlockdepÆôÓù¦ÄÜ¡£ - -16£ºËùÓеÄ/proc¼Ç¼¸üж¼Òª×÷³ÉÎļþ·ÅÔÚDocumentation/Ŀ¼Ï¡£ - -17£ºËùÓеÄÄÚºËÆô¶¯²ÎÊý¸üж¼±»¼Ç¼µ½Documentation/kernel-parameters.txtÎļþÖС£ - -18£ºËùÓеÄÄ£¿é²ÎÊý¸üж¼ÓÃMODULE_PARM_DESC()¼Ç¼¡£ - -19£ºËùÓеÄÓû§¿Õ¼ä½Ó¿Ú¸üж¼±»¼Ç¼µ½Documentation/ABI/¡£²é¿´Documentation/ABI/README - ¿ÉÒÔ»ñµÃ¸ü¶àµÄÐÅÏ¢¡£¸Ä±äÓû§¿Õ¼ä½Ó¿ÚµÄ²¹¶¡Ó¦¸Ã±»Óʼþ³­Ë͸ølinux-api@vger.kernel.org¡£ - -20£º¼ì²éËüÊDz»ÊǶ¼Í¨¹ý`make headers_check'¡£ - -21£ºÒѾ­Í¨¹ýÖÁÉÙÒýÈëslabºÍpage-allocationʧ°Ü¼ì²é¡£²é¿´Documentation/fault-injection/¡£ - -22£ºÐ¼ÓÈëµÄÔ´ÂëÒѾ­Í¨¹ý`gcc -W'£¨Ê¹ÓÃ"make EXTRA_CFLAGS=-W"£©±àÒë¡£ÕâÑù½«²úÉúºÜ¶à·³ÄÕ£¬ - µ«ÊǶÔÓÚÑ°ÕÒ©¶´ºÜÓÐÒæ´¦£¬ÀýÈç:"warning: comparison between signed and unsigned"¡£ - -23£ºµ±Ëü±»ºÏ²¢µ½-mm²¹¶¡¼¯ºóÔÙ²âÊÔ£¬ÓÃÀ´È·¶¨ËüÊÇ·ñ»¹ºÍ²¹¶¡¶ÓÁÐÖеÄÆäËû²¹¶¡Ò»Æð¹¤×÷ÒÔ¼°ÔÚVM£¬VFS - ºÍÆäËû×ÓϵͳÖи÷¸ö±ä»¯¡£ - -24£ºËùÓеÄÄÚ´æÆÁÕÏ{e.g., barrier(), rmb(), wmb()}ÐèÒªÔÚÔ´´úÂëÖеÄÒ»¸ö×¢ÊÍÀ´½âÊÍËûÃǶ¼ÊǸÉʲôµÄ - ÒÔ¼°Ô­Òò¡£ - -25£ºÈç¹ûÓÐÈκÎÊäÈëÊä³ö¿ØÖƵIJ¹¶¡±»Ìí¼Ó£¬Ò²Òª¸üÐÂDocumentation/ioctl/ioctl-number.txt¡£ - -26£ºÈç¹ûÄãµÄ¸ü¸Ä´úÂëÒÀ¿¿»òÕßʹÓÃÈκεÄÄÚºËAPIs»òÕßÓëÏÂÃæµÄkconfig·ûºÅÓйØϵµÄ¹¦ÄÜ£¬Äã¾ÍÒª - ʹÓÃÏà¹ØµÄkconfig·ûºÅ¹Ø±Õ£¬ and/or =m£¨Èç¹ûÑ¡ÏîÌṩ£©[ÔÚͬһʱ¼ä²»ÊÇËùÓõĶ¼ÆôÓ㬽ö½ö¸÷¸ö»òÕß×ÔÓÉ - ×éºÏËûÃÇ]£º - - CONFIG_SMP, CONFIG_SYSFS, CONFIG_PROC_FS, CONFIG_INPUT, CONFIG_PCI, - CONFIG_BLOCK, CONFIG_PM, CONFIG_HOTPLUG, CONFIG_MAGIC_SYSRQ, - CONFIG_NET, CONFIG_INET=n (ºóÒ»¸öʹÓà CONFIG_NET=y) diff --git a/MAINTAINERS b/MAINTAINERS index 5483e0c93b4bc2e0069c6af4e138b2bf5a937062..c406f9ba1923d377466e6453a5b21e936d4e9f53 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -117,20 +117,20 @@ Maintainers List (try to look for most precise areas first) M: Philip Blundell L: netdev@vger.kernel.org S: Maintained -F: drivers/net/3c505* +F: drivers/net/ethernet/i825xx/3c505* 3C59X NETWORK DRIVER M: Steffen Klassert L: netdev@vger.kernel.org S: Maintained F: Documentation/networking/vortex.txt -F: drivers/net/3c59x.c +F: drivers/net/ethernet/3com/3c59x.c 3CR990 NETWORK DRIVER M: David Dillow L: netdev@vger.kernel.org S: Maintained -F: drivers/net/typhoon* +F: drivers/net/ethernet/3com/typhoon* 3WARE SAS/SATA-RAID SCSI DRIVERS (3W-XXXX, 3W-9XXX, 3W-SAS) M: Adam Radford @@ -156,7 +156,7 @@ M: Realtek linux nic maintainers M: Francois Romieu L: netdev@vger.kernel.org S: Maintained -F: drivers/net/r8169.c +F: drivers/net/ethernet/realtek/r8169.c 8250/16?50 (AND CLONE UARTS) SERIAL DRIVER M: Greg Kroah-Hartman @@ -170,8 +170,7 @@ F: include/linux/serial_8250.h 8390 NETWORK DRIVERS [WD80x3/SMC-ELITE, SMC-ULTRA, NE2000, 3C503, etc.] L: netdev@vger.kernel.org S: Orphan / Obsolete -F: drivers/net/*8390* -F: drivers/net/ax88796.c +F: drivers/net/ethernet/8390/ 9P FILE SYSTEM M: Eric Van Hensbergen @@ -214,7 +213,7 @@ ACENIC DRIVER M: Jes Sorensen L: linux-acenic@sunsite.dk S: Maintained -F: drivers/net/acenic* +F: drivers/net/ethernet/alteon/acenic* ACER ASPIRE ONE TEMPERATURE AND FAN DRIVER M: Peter Feuerer @@ -317,6 +316,10 @@ W: http://wiki.analog.com/AD7879 S: Supported F: drivers/input/touchscreen/ad7879.c +ADDRESS SPACE LAYOUT RANDOMIZATION (ASLR) +M: Jiri Kosina +S: Maintained + ADM1025 HARDWARE MONITOR DRIVER M: Jean Delvare L: lm-sensors@lm-sensors.org @@ -530,6 +533,7 @@ S: Maintained F: drivers/infiniband/hw/amso1100/ ANALOG DEVICES INC ASOC CODEC DRIVERS +M: Lars-Peter Clausen L: device-drivers-devel@blackfin.uclinux.org L: alsa-devel@alsa-project.org (moderated for non-subscribers) W: http://wiki.analog.com/ @@ -688,6 +692,12 @@ F: drivers/mtd/nand/bcm_umi_nand.c F: drivers/mtd/nand/bcm_umi_bch.c F: drivers/mtd/nand/nand_bcm_umi.h +ARM/CALXEDA HIGHBANK ARCHITECTURE +M: Rob Herring +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +S: Maintained +F: arch/arm/mach-highbank/ + ARM/CAVIUM NETWORKS CNS3XXX MACHINE SUPPORT M: Anton Vorontsov S: Maintained @@ -746,7 +756,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) W: http://www.arm.linux.org.uk/ S: Maintained F: arch/arm/mach-ebsa110/ -F: drivers/net/arm/am79c961a.* +F: drivers/net/ethernet/amd/am79c961a.* ARM/EZX SMARTPHONES (A780, A910, A1200, E680, ROKR E2 and ROKR E6) M: Daniel Ribeiro @@ -787,6 +797,13 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: arch/arm/mach-mx5/ +ARM/FREESCALE IMX6 +M: Shawn Guo +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +S: Maintained +T: git git://git.linaro.org/people/shawnguo/linux-2.6.git +F: arch/arm/mach-imx/*imx6* + ARM/GLOMATION GESBC9312SX MACHINE SUPPORT M: Lennert Buytenhek L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) @@ -1015,7 +1032,8 @@ F: arch/arm/include/asm/hardware/ioc.h F: arch/arm/include/asm/hardware/iomd.h F: arch/arm/include/asm/hardware/memc.h F: arch/arm/mach-rpc/ -F: drivers/net/arm/ether* +F: drivers/net/ethernet/i825xx/ether1* +F: drivers/net/ethernet/seeq/ether3* F: drivers/scsi/arm/ ARM/SHARK MACHINE SUPPORT @@ -1084,6 +1102,24 @@ F: arch/arm/plat-s5p/dev-fimc* F: arch/arm/plat-samsung/include/plat/*fimc* F: drivers/media/video/s5p-fimc/ +ARM/SAMSUNG S5P SERIES Multi Format Codec (MFC) SUPPORT +M: Kyungmin Park +M: Kamil Debski +L: linux-arm-kernel@lists.infradead.org +L: linux-media@vger.kernel.org +S: Maintained +F: arch/arm/plat-s5p/dev-mfc.c +F: drivers/media/video/s5p-mfc/ + +ARM/SAMSUNG S5P SERIES TV SUBSYSTEM SUPPORT +M: Kyungmin Park +M: Tomasz Stanislawski +L: linux-arm-kernel@lists.infradead.org +L: linux-media@vger.kernel.org +S: Maintained +F: arch/arm/plat-s5p/dev-tv.c +F: drivers/media/video/s5p-tv/ + ARM/SHMOBILE ARM ARCHITECTURE M: Paul Mundt M: Magnus Damm @@ -1127,7 +1163,7 @@ F: arch/arm/mach-nuc93x/ F: drivers/input/keyboard/w90p910_keypad.c F: drivers/input/touchscreen/w90p910_ts.c F: drivers/watchdog/nuc900_wdt.c -F: drivers/net/arm/w90p910_ether.c +F: drivers/net/ethernet/nuvoton/w90p910_ether.c F: drivers/mtd/nand/nuc900_nand.c F: drivers/rtc/rtc-nuc900.c F: drivers/spi/spi_nuc900.c @@ -1230,7 +1266,7 @@ F: Documentation/aoe/ F: drivers/block/aoe/ ATHEROS ATH GENERIC UTILITIES -M: "Luis R. Rodriguez" +M: "Luis R. Rodriguez" L: linux-wireless@vger.kernel.org S: Supported F: drivers/net/wireless/ath/* @@ -1238,7 +1274,7 @@ F: drivers/net/wireless/ath/* ATHEROS ATH5K WIRELESS DRIVER M: Jiri Slaby M: Nick Kossifidis -M: "Luis R. Rodriguez" +M: "Luis R. Rodriguez" M: Bob Copeland L: linux-wireless@vger.kernel.org L: ath5k-devel@lists.ath5k.org @@ -1246,11 +1282,19 @@ W: http://wireless.kernel.org/en/users/Drivers/ath5k S: Maintained F: drivers/net/wireless/ath/ath5k/ +ATHEROS ATH6KL WIRELESS DRIVER +M: Kalle Valo +L: linux-wireless@vger.kernel.org +W: http://wireless.kernel.org/en/users/Drivers/ath6kl +T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath6kl.git +S: Supported +F: drivers/net/wireless/ath/ath6kl/ + ATHEROS ATH9K WIRELESS DRIVER -M: "Luis R. Rodriguez" -M: Jouni Malinen -M: Vasanthakumar Thiagarajan -M: Senthil Balasubramanian +M: "Luis R. Rodriguez" +M: Jouni Malinen +M: Vasanthakumar Thiagarajan +M: Senthil Balasubramanian L: linux-wireless@vger.kernel.org L: ath9k-devel@lists.ath9k.org W: http://wireless.kernel.org/en/users/Drivers/ath9k @@ -1282,7 +1326,7 @@ L: netdev@vger.kernel.org W: http://sourceforge.net/projects/atl1 W: http://atl1.sourceforge.net S: Maintained -F: drivers/net/atlx/ +F: drivers/net/ethernet/atheros/ ATM M: Chas Williams @@ -1322,7 +1366,7 @@ F: include/video/atmel_lcdc.h ATMEL MACB ETHERNET DRIVER M: Nicolas Ferre S: Supported -F: drivers/net/macb.* +F: drivers/net/ethernet/cadence/ ATMEL SPI DRIVER M: Nicolas Ferre @@ -1445,7 +1489,7 @@ BLACKFIN EMAC DRIVER L: uclinux-dist-devel@blackfin.uclinux.org W: http://blackfin.uclinux.org S: Supported -F: drivers/net/bfin_mac.* +F: drivers/net/ethernet/adi/ BLACKFIN RTC DRIVER M: Mike Frysinger @@ -1526,27 +1570,27 @@ BROADCOM B44 10/100 ETHERNET DRIVER M: Gary Zambrano L: netdev@vger.kernel.org S: Supported -F: drivers/net/b44.* +F: drivers/net/ethernet/broadcom/b44.* BROADCOM BNX2 GIGABIT ETHERNET DRIVER M: Michael Chan L: netdev@vger.kernel.org S: Supported -F: drivers/net/bnx2.* -F: drivers/net/bnx2_* +F: drivers/net/ethernet/broadcom/bnx2.* +F: drivers/net/ethernet/broadcom/bnx2_* BROADCOM BNX2X 10 GIGABIT ETHERNET DRIVER M: Eilon Greenstein L: netdev@vger.kernel.org S: Supported -F: drivers/net/bnx2x/ +F: drivers/net/ethernet/broadcom/bnx2x/ BROADCOM TG3 GIGABIT ETHERNET DRIVER M: Matt Carlson M: Michael Chan L: netdev@vger.kernel.org S: Supported -F: drivers/net/tg3.* +F: drivers/net/ethernet/broadcom/tg3.* BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER M: Brett Rudley @@ -1575,7 +1619,7 @@ BROCADE BNA 10 GIGABIT ETHERNET DRIVER M: Rasesh Mody L: netdev@vger.kernel.org S: Supported -F: drivers/net/bna/ +F: drivers/net/ethernet/brocade/bna/ BSG (block layer generic sg v4 driver) M: FUJITA Tomonori @@ -1663,7 +1707,7 @@ CAN NETWORK LAYER M: Oliver Hartkopp M: Oliver Hartkopp M: Urs Thuermann -L: socketcan-core@lists.berlios.de (subscribers-only) +L: linux-can@vger.kernel.org L: netdev@vger.kernel.org W: http://developer.berlios.de/projects/socketcan/ S: Maintained @@ -1675,7 +1719,7 @@ F: include/linux/can/raw.h CAN NETWORK DRIVERS M: Wolfgang Grandegger -L: socketcan-core@lists.berlios.de (subscribers-only) +L: linux-can@vger.kernel.org L: netdev@vger.kernel.org W: http://developer.berlios.de/projects/socketcan/ S: Maintained @@ -1759,13 +1803,13 @@ M: Christian Benvenuti M: Roopa Prabhu M: David Wang S: Supported -F: drivers/net/enic/ +F: drivers/net/ethernet/cisco/enic/ CIRRUS LOGIC EP93XX ETHERNET DRIVER M: Hartley Sweeten L: netdev@vger.kernel.org S: Maintained -F: drivers/net/arm/ep93xx_eth.c +F: drivers/net/ethernet/cirrus/ep93xx_eth.c CIRRUS LOGIC EP93XX OHCI USB HOST DRIVER M: Lennert Buytenhek @@ -1905,7 +1949,7 @@ CPMAC ETHERNET DRIVER M: Florian Fainelli L: netdev@vger.kernel.org S: Maintained -F: drivers/net/cpmac.c +F: drivers/net/ethernet/ti/cpmac.c CPU FREQUENCY DRIVERS M: Dave Jones @@ -1992,7 +2036,7 @@ M: Divy Le Ray L: netdev@vger.kernel.org W: http://www.chelsio.com S: Supported -F: drivers/net/cxgb3/ +F: drivers/net/ethernet/chelsio/cxgb3/ CXGB3 IWARP RNIC DRIVER (IW_CXGB3) M: Steve Wise @@ -2006,7 +2050,7 @@ M: Dimitris Michailidis L: netdev@vger.kernel.org W: http://www.chelsio.com S: Supported -F: drivers/net/cxgb4/ +F: drivers/net/ethernet/chelsio/cxgb4/ CXGB4 IWARP RNIC DRIVER (IW_CXGB4) M: Steve Wise @@ -2020,14 +2064,14 @@ M: Casey Leedom L: netdev@vger.kernel.org W: http://www.chelsio.com S: Supported -F: drivers/net/cxgb4vf/ +F: drivers/net/ethernet/chelsio/cxgb4vf/ STMMAC ETHERNET DRIVER M: Giuseppe Cavallaro L: netdev@vger.kernel.org W: http://www.stlinux.com S: Supported -F: drivers/net/stmmac/ +F: drivers/net/ethernet/stmicro/stmmac/ CYBERPRO FB DRIVER M: Russell King @@ -2071,7 +2115,7 @@ DAVICOM FAST ETHERNET (DMFE) NETWORK DRIVER L: netdev@vger.kernel.org S: Orphan F: Documentation/networking/dmfe.txt -F: drivers/net/tulip/dmfe.c +F: drivers/net/ethernet/tulip/dmfe.c DC390/AM53C974 SCSI driver M: Kurt Garloff @@ -2110,7 +2154,7 @@ F: net/decnet/ DEFXX FDDI NETWORK DRIVER M: "Maciej W. Rozycki" S: Maintained -F: drivers/net/defxx.* +F: drivers/net/fddi/defxx.* DELL LAPTOP DRIVER M: Matthew Garrett @@ -2136,6 +2180,14 @@ M: Matthew Garrett S: Maintained F: drivers/platform/x86/dell-wmi.c +DESIGNWARE USB3 DRD IP DRIVER +M: Felipe Balbi +L: linux-usb@vger.kernel.org +L: linux-omap@vger.kernel.org +T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git +S: Maintained +F: drivers/usb/dwc3/ + DEVICE NUMBER REGISTRY M: Torben Mathiasen W: http://lanana.org/docs/device-list/index.html @@ -2294,6 +2346,12 @@ L: netdev@vger.kernel.org S: Maintained F: drivers/net/wan/dscc4.c +DYNAMIC DEBUG +M: Jason Baron +S: Maintained +F: lib/dynamic_debug.c +F: include/linux/dynamic_debug.h + DZ DECSTATION DZ11 SERIAL DRIVER M: "Maciej W. Rozycki" S: Maintained @@ -2460,10 +2518,10 @@ S: Supported F: drivers/infiniband/hw/ehca/ EHEA (IBM pSeries eHEA 10Gb ethernet adapter) DRIVER -M: Breno Leitao +M: Thadeu Lima de Souza Cascardo L: netdev@vger.kernel.org S: Maintained -F: drivers/net/ehea/ +F: drivers/net/ethernet/ibm/ehea/ EMBEDDED LINUX M: Paul Gortmaker @@ -2508,7 +2566,7 @@ ETHEREXPRESS-16 NETWORK DRIVER M: Philip Blundell L: netdev@vger.kernel.org S: Maintained -F: drivers/net/eexpress.* +F: drivers/net/ethernet/i825xx/eexpress.* ETHERNET BRIDGE M: Stephen Hemminger @@ -2522,7 +2580,7 @@ F: net/bridge/ ETHERTEAM 16I DRIVER M: Mika Kuoppala S: Maintained -F: drivers/net/eth16i.c +F: drivers/net/ethernet/fujitsu/eth16i.c EXT2 FILE SYSTEM M: Jan Kara @@ -2552,6 +2610,11 @@ S: Maintained F: Documentation/filesystems/ext4.txt F: fs/ext4/ +Extended Verification Module (EVM) +M: Mimi Zohar +S: Supported +F: security/integrity/evm/ + F71805F HARDWARE MONITORING DRIVER M: Jean Delvare L: lm-sensors@lm-sensors.org @@ -2686,7 +2749,7 @@ M: Vitaly Bordug L: linuxppc-dev@lists.ozlabs.org L: netdev@vger.kernel.org S: Maintained -F: drivers/net/fs_enet/ +F: drivers/net/ethernet/freescale/fs_enet/ F: include/linux/fs_enet_pd.h FREESCALE QUICC ENGINE LIBRARY @@ -2708,7 +2771,7 @@ M: Li Yang L: netdev@vger.kernel.org L: linuxppc-dev@lists.ozlabs.org S: Maintained -F: drivers/net/ucc_geth* +F: drivers/net/ethernet/freescale/ucc_geth* FREESCALE QUICC ENGINE UCC UART DRIVER M: Timur Tabi @@ -2733,7 +2796,7 @@ F: fs/freevxfs/ FREEZER M: Pavel Machek M: "Rafael J. Wysocki" -L: linux-pm@lists.linux-foundation.org +L: linux-pm@vger.kernel.org S: Supported F: Documentation/power/freezing-of-tasks.txt F: include/linux/freezer.h @@ -2995,7 +3058,7 @@ F: drivers/video/hgafb.c HIBERNATION (aka Software Suspend, aka swsusp) M: Pavel Machek M: "Rafael J. Wysocki" -L: linux-pm@lists.linux-foundation.org +L: linux-pm@vger.kernel.org S: Supported F: arch/x86/power/ F: drivers/base/power/ @@ -3046,6 +3109,7 @@ S: Maintained F: include/linux/hippidevice.h F: include/linux/if_hippi.h F: net/802/hippi.c +F: drivers/net/hippi/ HOST AP DRIVER M: Jouni Malinen @@ -3063,7 +3127,7 @@ F: drivers/platform/x86/tc1100-wmi.c HP100: Driver for HP 10/100 Mbit/s Voice Grade Network Adapter Series M: Jaroslav Kysela S: Maintained -F: drivers/net/hp100.* +F: drivers/net/ethernet/hp/hp100.* HPET: High Precision Event Timers driver M: Clemens Ladisch @@ -3161,7 +3225,7 @@ IBM Power Virtual Ethernet Device Driver M: Santiago Leon L: netdev@vger.kernel.org S: Supported -F: drivers/net/ibmveth.* +F: drivers/net/ethernet/ibm/ibmveth.* IBM ServeRAID RAID DRIVER P: Jack Hammer @@ -3180,6 +3244,13 @@ F: Documentation/ide/ F: drivers/ide/ F: include/linux/ide.h +IDEAPAD LAPTOP EXTRAS DRIVER +M: Ike Panhc +L: platform-driver-x86@vger.kernel.org +W: http://launchpad.net/ideapad-laptop +S: Maintained +F: drivers/platform/x86/ideapad-laptop.c + IDE/ATAPI DRIVERS M: Borislav Petkov L: linux-ide@vger.kernel.org @@ -3189,7 +3260,7 @@ F: drivers/ide/ide-cd* IDLE-I7300 M: Andy Henroid -L: linux-pm@lists.linux-foundation.org +L: linux-pm@vger.kernel.org S: Supported F: drivers/idle/i7300_idle.c @@ -3272,7 +3343,7 @@ F: firmware/isci/ INTEL IDLE DRIVER M: Len Brown -L: linux-pm@lists.linux-foundation.org +L: linux-pm@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-idle-2.6.git S: Supported F: drivers/idle/intel_idle.c @@ -3313,7 +3384,7 @@ M: David Woodhouse L: iommu@lists.linux-foundation.org T: git git://git.infradead.org/iommu-2.6.git S: Supported -F: drivers/pci/intel-iommu.c +F: drivers/iommu/intel-iommu.c F: include/linux/intel-iommu.h INTEL IOP-ADMA DMA DRIVER @@ -3328,7 +3399,7 @@ F: arch/arm/mach-ixp4xx/include/mach/qmgr.h F: arch/arm/mach-ixp4xx/include/mach/npe.h F: arch/arm/mach-ixp4xx/ixp4xx_qmgr.c F: arch/arm/mach-ixp4xx/ixp4xx_npe.c -F: drivers/net/arm/ixp4xx_eth.c +F: drivers/net/ethernet/xscale/ixp4xx_eth.c F: drivers/net/wan/ixp4xx_hss.c INTEL IXP4XX RANDOM NUMBER GENERATOR SUPPORT @@ -3340,7 +3411,7 @@ INTEL IXP2000 ETHERNET DRIVER M: Lennert Buytenhek L: netdev@vger.kernel.org S: Maintained -F: drivers/net/ixp2000/ +F: drivers/net/ethernet/xscale/ixp2000/ INTEL ETHERNET DRIVERS (e100/e1000/e1000e/igb/igbvf/ixgb/ixgbe/ixgbevf) M: Jeff Kirsher @@ -3349,13 +3420,13 @@ M: Bruce Allan M: Carolyn Wyborny M: Don Skidmore M: Greg Rose -M: PJ Waskiewicz +M: Peter P Waskiewicz Jr M: Alex Duyck M: John Ronciak L: e1000-devel@lists.sourceforge.net W: http://e1000.sourceforge.net/ -T: git git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-2.6.git -T: git git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next.git S: Supported F: Documentation/networking/e100.txt F: Documentation/networking/e1000.txt @@ -3365,18 +3436,11 @@ F: Documentation/networking/igbvf.txt F: Documentation/networking/ixgb.txt F: Documentation/networking/ixgbe.txt F: Documentation/networking/ixgbevf.txt -F: drivers/net/e100.c -F: drivers/net/e1000/ -F: drivers/net/e1000e/ -F: drivers/net/igb/ -F: drivers/net/igbvf/ -F: drivers/net/ixgb/ -F: drivers/net/ixgbe/ -F: drivers/net/ixgbevf/ +F: drivers/net/ethernet/intel/ INTEL MRST PMU DRIVER M: Len Brown -L: linux-pm@lists.linux-foundation.org +L: linux-pm@vger.kernel.org S: Supported F: arch/x86/platform/mrst/pmu.* @@ -3424,7 +3488,7 @@ M: Wey-Yi Guy M: Intel Linux Wireless L: linux-wireless@vger.kernel.org W: http://intellinuxwireless.org -T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi.git S: Supported F: drivers/net/wireless/iwlwifi/ @@ -3440,7 +3504,7 @@ IOC3 ETHERNET DRIVER M: Ralf Baechle L: linux-mips@linux-mips.org S: Maintained -F: drivers/net/ioc3-eth.c +F: drivers/net/ethernet/sgi/ioc3-eth.c IOC3 SERIAL DRIVER M: Pat Gefre @@ -3458,7 +3522,7 @@ M: Francois Romieu M: Sorbica Shieh L: netdev@vger.kernel.org S: Maintained -F: drivers/net/ipg.* +F: drivers/net/ethernet/icplus/ipg.* IPATH DRIVER M: Mike Marciniszyn @@ -3606,7 +3670,7 @@ JME NETWORK DRIVER M: Guo-Fu Tseng L: netdev@vger.kernel.org S: Maintained -F: drivers/net/jme.* +F: drivers/net/ethernet/jme.* JOURNALLING FLASH FILE SYSTEM V2 (JFFS2) M: David Woodhouse @@ -3973,6 +4037,7 @@ M: Eric Piel S: Maintained F: Documentation/misc-devices/lis3lv02d F: drivers/misc/lis3lv02d/ +F: drivers/platform/x86/hp_accel.c LLC (802.2) M: Arnaldo Carvalho de Melo @@ -4067,7 +4132,7 @@ S: Maintained M32R ARCHITECTURE M: Hirokazu Takata -L: linux-m32r@ml.linux-m32r.org +L: linux-m32r@ml.linux-m32r.org (moderated for non-subscribers) L: linux-m32r-ja@ml.linux-m32r.org (in Japanese) W: http://www.linux-m32r.org/ S: Maintained @@ -4137,7 +4202,7 @@ MARVELL MV643XX ETHERNET DRIVER M: Lennert Buytenhek L: netdev@vger.kernel.org S: Maintained -F: drivers/net/mv643xx_eth.* +F: drivers/net/ethernet/marvell/mv643xx_eth.* F: include/linux/mv643xx.h MARVELL MWIFIEX WIRELESS DRIVER @@ -4236,7 +4301,7 @@ F: include/mtd/ MICROBLAZE ARCHITECTURE M: Michal Simek -L: microblaze-uclinux@itee.uq.edu.au +L: microblaze-uclinux@itee.uq.edu.au (moderated for non-subscribers) W: http://www.monstr.eu/fdt/ T: git git://git.monstr.eu/linux-2.6-microblaze.git S: Supported @@ -4351,12 +4416,12 @@ M: Andrew Gallatin L: netdev@vger.kernel.org W: http://www.myri.com/scs/download-Myri10GE.html S: Supported -F: drivers/net/myri10ge/ +F: drivers/net/ethernet/myricom/myri10ge/ NATSEMI ETHERNET DRIVER (DP8381x) M: Tim Hockin S: Maintained -F: drivers/net/natsemi.c +F: drivers/net/ethernet/natsemi/natsemi.c NATIVE INSTRUMENTS USB SOUND INTERFACE DRIVER M: Daniel Mack @@ -4396,9 +4461,8 @@ W: http://trac.neterion.com/cgi-bin/trac.cgi/wiki/Linux?Anonymous W: http://trac.neterion.com/cgi-bin/trac.cgi/wiki/X3100Linux?Anonymous S: Supported F: Documentation/networking/s2io.txt -F: drivers/net/s2io* F: Documentation/networking/vxge.txt -F: drivers/net/vxge/ +F: drivers/net/ethernet/neterion/ NETFILTER/IPTABLES/IPCHAINS P: Rusty Russell @@ -4512,11 +4576,23 @@ F: include/linux/if_* F: include/linux/*device.h NETXEN (1/10) GbE SUPPORT -M: Amit Kumar Salecha +M: Sony Chacko +M: Rajesh Borundia L: netdev@vger.kernel.org W: http://www.qlogic.com S: Supported -F: drivers/net/netxen/ +F: drivers/net/ethernet/qlogic/netxen/ + +NFC SUBSYSTEM +M: Lauro Ramos Venancio +M: Aloisio Almeida Jr +M: Samuel Ortiz +L: linux-wireless@vger.kernel.org +S: Maintained +F: net/nfc/ +F: include/linux/nfc.h +F: include/net/nfc/ +F: drivers/nfc/ NFS, SUNRPC, AND LOCKD CLIENTS M: Trond Myklebust @@ -4537,7 +4613,7 @@ M: Jan-Pascal van Best M: Andreas Mohr L: netdev@vger.kernel.org S: Maintained -F: drivers/net/ni5010.* +F: drivers/net/ethernet/racal/ni5010.* NILFS2 FILESYSTEM M: KONISHI Ryusuke @@ -4728,10 +4804,12 @@ F: drivers/i2c/busses/i2c-ocores.c OPEN FIRMWARE AND FLATTENED DEVICE TREE M: Grant Likely +M: Rob Herring L: devicetree-discuss@lists.ozlabs.org (moderated for non-subscribers) W: http://fdt.secretlab.ca T: git git://git.secretlab.ca/git/linux-2.6.git S: Maintained +F: Documentation/devicetree F: drivers/of F: include/linux/of*.h K: of_get_property @@ -4740,7 +4818,7 @@ K: of_match_table OPENRISC ARCHITECTURE M: Jonas Bonn W: http://openrisc.net -L: linux@lists.openrisc.net +L: linux@lists.openrisc.net (moderated for non-subscribers) S: Maintained T: git git://openrisc.net/~jonas/linux F: arch/openrisc @@ -4803,7 +4881,7 @@ PA SEMI ETHERNET DRIVER M: Olof Johansson L: netdev@vger.kernel.org S: Maintained -F: drivers/net/pasemi_mac.* +F: drivers/net/ethernet/pasemi/* PA SEMI SMBUS DRIVER M: Olof Johansson @@ -4914,7 +4992,7 @@ F: include/linux/i2c-algo-pca.h F: include/linux/i2c-pca-platform.h PCI ERROR RECOVERY -M: Linas Vepstas +M: Linas Vepstas L: linux-pci@vger.kernel.org S: Supported F: Documentation/PCI/pci-error-recovery.txt @@ -4950,7 +5028,7 @@ PCNET32 NETWORK DRIVER M: Don Fry L: netdev@vger.kernel.org S: Maintained -F: drivers/net/pcnet32.c +F: drivers/net/ethernet/amd/pcnet32.c PCRYPT PARALLEL CRYPTO ENGINE M: Steffen Klassert @@ -5010,6 +5088,11 @@ L: linux-mtd@lists.infradead.org S: Maintained F: drivers/mtd/devices/phram.c +PIN CONTROL SUBSYSTEM +M: Linus Walleij +S: Maintained +F: drivers/pinmux/ + PKTCDVD DRIVER M: Peter Osterlund S: Maintained @@ -5082,7 +5165,7 @@ PPP PROTOCOL DRIVERS AND COMPRESSORS M: Paul Mackerras L: linux-ppp@vger.kernel.org S: Maintained -F: drivers/net/ppp_* +F: drivers/net/ppp/ppp_* PPP OVER ATM (RFC 2364) M: Mitchell Blank Jr @@ -5093,8 +5176,8 @@ F: include/linux/atmppp.h PPP OVER ETHERNET M: Michal Ostrowski S: Maintained -F: drivers/net/pppoe.c -F: drivers/net/pppox.c +F: drivers/net/ppp/pppoe.c +F: drivers/net/ppp/pppox.c PPP OVER L2TP M: James Chapman @@ -5115,7 +5198,7 @@ PPTP DRIVER M: Dmitry Kozlov L: netdev@vger.kernel.org S: Maintained -F: drivers/net/pptp.c +F: drivers/net/ppp/pptp.c W: http://sourceforge.net/projects/accel-pptp PREEMPTIBLE KERNEL @@ -5144,7 +5227,7 @@ M: Geoff Levand L: netdev@vger.kernel.org L: cbe-oss-dev@lists.ozlabs.org S: Maintained -F: drivers/net/ps3_gelic_net.* +F: drivers/net/ethernet/toshiba/ps3_gelic_net.* PS3 PLATFORM SUPPORT M: Geoff Levand @@ -5262,23 +5345,24 @@ M: linux-driver@qlogic.com L: netdev@vger.kernel.org S: Supported F: Documentation/networking/LICENSE.qla3xxx -F: drivers/net/qla3xxx.* +F: drivers/net/ethernet/qlogic/qla3xxx.* QLOGIC QLCNIC (1/10)Gb ETHERNET DRIVER -M: Amit Kumar Salecha M: Anirban Chakraborty +M: Sony Chacko M: linux-driver@qlogic.com L: netdev@vger.kernel.org S: Supported -F: drivers/net/qlcnic/ +F: drivers/net/ethernet/qlogic/qlcnic/ QLOGIC QLGE 10Gb ETHERNET DRIVER +M: Anirban Chakraborty M: Jitendra Kalsaria M: Ron Mercer M: linux-driver@qlogic.com L: netdev@vger.kernel.org S: Supported -F: drivers/net/qlge/ +F: drivers/net/ethernet/qlogic/qlge/ QNX4 FILESYSTEM M: Anders Larsen @@ -5288,6 +5372,12 @@ F: fs/qnx4/ F: include/linux/qnx4_fs.h F: include/linux/qnxtypes.h +QUALCOMM HEXAGON ARCHITECTURE +M: Richard Kuo +L: linux-hexagon@vger.kernel.org +S: Supported +F: arch/hexagon/ + RADOS BLOCK DEVICE (RBD) F: include/linux/qnxtypes.h M: Yehuda Sadeh @@ -5360,7 +5450,7 @@ RDC R6040 FAST ETHERNET DRIVER M: Florian Fainelli L: netdev@vger.kernel.org S: Maintained -F: drivers/net/r6040.c +F: drivers/net/ethernet/rdc/r6040.c RDS - RELIABLE DATAGRAM SOCKETS M: Andy Grover @@ -5764,7 +5854,7 @@ M: Ajit Khaparde L: netdev@vger.kernel.org W: http://www.emulex.com S: Supported -F: drivers/net/benet/ +F: drivers/net/ethernet/emulex/benet/ SFC NETWORK DRIVER M: Solarflare linux maintainers @@ -5772,7 +5862,7 @@ M: Steve Hodgson M: Ben Hutchings L: netdev@vger.kernel.org S: Supported -F: drivers/net/sfc/ +F: drivers/net/ethernet/sfc/ SGI GRU DRIVER M: Jack Steiner @@ -5838,14 +5928,14 @@ SIS 190 ETHERNET DRIVER M: Francois Romieu L: netdev@vger.kernel.org S: Maintained -F: drivers/net/sis190.c +F: drivers/net/ethernet/sis/sis190.c SIS 900/7016 FAST ETHERNET DRIVER M: Daniele Venzano W: http://www.brownhat.org/sis900.html L: netdev@vger.kernel.org S: Maintained -F: drivers/net/sis900.* +F: drivers/net/ethernet/sis/sis900.* SIS 96X I2C/SMBUS DRIVER M: "Mark M. Hoffman" @@ -5872,8 +5962,7 @@ SKGE, SKY2 10/100/1000 GIGABIT ETHERNET DRIVERS M: Stephen Hemminger L: netdev@vger.kernel.org S: Maintained -F: drivers/net/skge.* -F: drivers/net/sky2.* +F: drivers/net/ethernet/marvell/sk* SLAB ALLOCATOR M: Christoph Lameter @@ -5887,7 +5976,7 @@ F: mm/sl?b.c SMC91x ETHERNET DRIVER M: Nicolas Pitre S: Odd Fixes -F: drivers/net/smc91x.* +F: drivers/net/ethernet/smsc/smc91x.* SMM665 HARDWARE MONITOR DRIVER M: Guenter Roeck @@ -5922,13 +6011,19 @@ M: Steve Glendinning L: netdev@vger.kernel.org S: Supported F: include/linux/smsc911x.h -F: drivers/net/smsc911x.* +F: drivers/net/ethernet/smsc/smsc911x.* SMSC9420 PCI ETHERNET DRIVER M: Steve Glendinning L: netdev@vger.kernel.org S: Supported -F: drivers/net/smsc9420.* +F: drivers/net/ethernet/smsc/smsc9420.* + +SMSC UFX6000 and UFX7000 USB to VGA DRIVER +M: Steve Glendinning +L: linux-fbdev@vger.kernel.org +S: Supported +F: drivers/video/smscufx.c SN-IA64 (Itanium) SUB-PLATFORM M: Jes Sorensen @@ -5962,7 +6057,7 @@ SONIC NETWORK DRIVER M: Thomas Bogendoerfer L: netdev@vger.kernel.org S: Maintained -F: drivers/net/sonic.* +F: drivers/net/ethernet/natsemi/sonic.* SONICS SILICON BACKPLANE DRIVER (SSB) M: Michael Buesch @@ -5999,7 +6094,7 @@ M: Jaroslav Kysela M: Takashi Iwai L: alsa-devel@alsa-project.org (moderated for non-subscribers) W: http://www.alsa-project.org/ -T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git T: git git://git.alsa-project.org/alsa-kernel.git S: Maintained F: Documentation/sound/ @@ -6103,7 +6198,7 @@ M: Jens Osterkamp L: netdev@vger.kernel.org S: Supported F: Documentation/networking/spider_net.txt -F: drivers/net/spider_net* +F: drivers/net/ethernet/toshiba/spider_net* SPU FILE SYSTEM M: Jeremy Kerr @@ -6134,7 +6229,7 @@ S: Maintained STAGING SUBSYSTEM M: Greg Kroah-Hartman -T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git L: devel@driverdev.osuosl.org S: Maintained F: drivers/staging/ @@ -6150,12 +6245,6 @@ M: Jakub Schmidtke S: Odd Fixes F: drivers/staging/asus_oled/ -STAGING - ATHEROS ATH6KL WIRELESS DRIVER -M: Luis R. Rodriguez -M: Naveen Singh -S: Odd Fixes -F: drivers/staging/ath6kl/ - STAGING - COMEDI M: Ian Abbott M: Mori Hess @@ -6181,6 +6270,11 @@ M: David Rowe S: Odd Fixes F: drivers/staging/echo/ +STAGING - ET131X NETWORK DRIVER +M: Mark Einon +S: Odd Fixes +F: drivers/staging/et131x/ + STAGING - FLARION FT1000 DRIVERS M: Marek Belisko S: Odd Fixes @@ -6209,6 +6303,13 @@ W: http://www.lirc.org/ S: Odd Fixes F: drivers/staging/lirc/ +STAGING - NVIDIA COMPLIANT EMBEDDED CONTROLLER INTERFACE (nvec) +M: Julian Andres Klode +M: Marc Dietrich +L: ac100@lists.launchpad.net (moderated for non-subscribers) +S: Maintained +F: drivers/staging/nvec/ + STAGING - OLPC SECONDARY DISPLAY CONTROLLER (DCON) M: Andres Salomon M: Chris Ball @@ -6281,7 +6382,7 @@ F: drivers/staging/xgifb/ STARFIRE/DURALAN NETWORK DRIVER M: Ion Badulescu S: Odd Fixes -F: drivers/net/starfire* +F: drivers/net/ethernet/adaptec/starfire* SUN3/3X M: Sam Creasey @@ -6290,6 +6391,7 @@ S: Maintained F: arch/m68k/kernel/*sun3* F: arch/m68k/sun3*/ F: arch/m68k/include/asm/sun3* +F: drivers/net/ethernet/i825xx/sun3* SUPERH M: Paul Mundt @@ -6306,7 +6408,7 @@ SUSPEND TO RAM M: Len Brown M: Pavel Machek M: "Rafael J. Wysocki" -L: linux-pm@lists.linux-foundation.org +L: linux-pm@vger.kernel.org S: Supported F: Documentation/power/ F: arch/x86/kernel/acpi/ @@ -6377,7 +6479,7 @@ TEHUTI ETHERNET DRIVER M: Andy Gospodarek L: netdev@vger.kernel.org S: Supported -F: drivers/net/tehuti* +F: drivers/net/ethernet/tehuti/* Telecom Clock Driver for MCPL0010 M: Mark Gross @@ -6428,7 +6530,7 @@ W: http://www.tilera.com/scm/ S: Supported F: arch/tile/ F: drivers/tty/hvc/hvc_tile.c -F: drivers/net/tile/ +F: drivers/net/ethernet/tile/ F: drivers/edac/tile_edac.c TLAN NETWORK DRIVER @@ -6437,7 +6539,7 @@ L: tlan-devel@lists.sourceforge.net (subscribers-only) W: http://sourceforge.net/projects/tlan/ S: Maintained F: Documentation/networking/tlan.txt -F: drivers/net/tlan.* +F: drivers/net/ethernet/ti/tlan.* TOMOYO SECURITY MODULE M: Kentaro Takeda @@ -6447,7 +6549,7 @@ L: tomoyo-users-en@lists.sourceforge.jp (subscribers-only, for users in English) L: tomoyo-dev@lists.sourceforge.jp (subscribers-only, for developers in Japanese) L: tomoyo-users@lists.sourceforge.jp (subscribers-only, for users in Japanese) W: http://tomoyo.sourceforge.jp/ -T: quilt http://svn.sourceforge.jp/svnroot/tomoyo/trunk/2.4.x/tomoyo-lsm/patches/ +T: quilt http://svn.sourceforge.jp/svnroot/tomoyo/trunk/2.5.x/tomoyo-lsm/patches/ S: Maintained F: security/tomoyo/ @@ -6531,7 +6633,7 @@ TULIP NETWORK DRIVERS M: Grant Grundler L: netdev@vger.kernel.org S: Maintained -F: drivers/net/tulip/ +F: drivers/net/ethernet/tulip/ TUN/TAP driver M: Maxim Krasnyansky @@ -6577,7 +6679,7 @@ W: http://uclinux-h8.sourceforge.jp/ S: Supported F: arch/h8300/ F: drivers/ide/ide-h8300.c -F: drivers/net/ne-h8300.c +F: drivers/net/ethernet/8390/ne-h8300.c UDF FILESYSTEM M: Jan Kara @@ -7005,7 +7107,7 @@ F: include/linux/vhost.h VIA RHINE NETWORK DRIVER M: Roger Luethi S: Maintained -F: drivers/net/via-rhine.c +F: drivers/net/ethernet/via/via-rhine.c VIAPRO SMBUS DRIVER M: Jean Delvare @@ -7033,7 +7135,7 @@ VIA VELOCITY NETWORK DRIVER M: Francois Romieu L: netdev@vger.kernel.org S: Maintained -F: drivers/net/via-velocity.* +F: drivers/net/ethernet/via/via-velocity.* VLAN (802.1Q) M: Patrick McHardy @@ -7142,6 +7244,12 @@ L: linux-scsi@vger.kernel.org S: Maintained F: drivers/scsi/wd7000.c +WIIMOTE HID DRIVER +M: David Herrmann +L: linux-input@vger.kernel.org +S: Maintained +F: drivers/hid/hid-wiimote* + WINBOND CIR DRIVER M: David Härdeman S: Maintained @@ -7207,6 +7315,7 @@ T: git git://opensource.wolfsonmicro.com/linux-2.6-audioplus W: http://opensource.wolfsonmicro.com/content/linux-drivers-wolfson-devices S: Supported F: Documentation/hwmon/wm83?? +F: arch/arm/mach-s3c64xx/mach-crag6410* F: drivers/leds/leds-wm83*.c F: drivers/input/misc/wm831x-on.c F: drivers/input/touchscreen/wm831x-ts.c diff --git a/Makefile b/Makefile index 2652089bf5412ee430087fde695d635e46026694..07bc92544e9cab9ea9fd201b8a5f36fb9dbb9168 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 1 SUBLEVEL = 0 -EXTRAVERSION = -rc10 +EXTRAVERSION = NAME = "Divemaster Edition" # *DOCUMENTATION* diff --git a/arch/alpha/include/asm/fcntl.h b/arch/alpha/include/asm/fcntl.h index 1b71ca70c9f679da3a0aeac5f62756e7fe918513..6d9e805f18a77266504ab8217eaeb2310ec9532c 100644 --- a/arch/alpha/include/asm/fcntl.h +++ b/arch/alpha/include/asm/fcntl.h @@ -51,8 +51,6 @@ #define F_EXLCK 16 /* or 3 */ #define F_SHLCK 32 /* or 4 */ -#define F_INPROGRESS 64 - #include #endif diff --git a/arch/alpha/include/asm/unistd.h b/arch/alpha/include/asm/unistd.h index 4ac48a095f3ace676d7f4651dedf21a84da9249b..2207fc61665d0526a03940d26d3c282240af58d6 100644 --- a/arch/alpha/include/asm/unistd.h +++ b/arch/alpha/include/asm/unistd.h @@ -457,10 +457,12 @@ #define __NR_clock_adjtime 499 #define __NR_syncfs 500 #define __NR_setns 501 +#define __NR_accept4 502 +#define __NR_sendmmsg 503 #ifdef __KERNEL__ -#define NR_SYSCALLS 502 +#define NR_SYSCALLS 504 #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR diff --git a/arch/alpha/kernel/srm_env.c b/arch/alpha/kernel/srm_env.c index f0df3fbd84025eff9bf304fd179bed8785e865dc..b9fc6c309d2ea35f22ec6c89b7469d899e94a773 100644 --- a/arch/alpha/kernel/srm_env.c +++ b/arch/alpha/kernel/srm_env.c @@ -4,9 +4,8 @@ * * (C) 2001,2002,2006 by Jan-Benedict Glaw * - * This driver is at all a modified version of Erik Mouw's - * Documentation/DocBook/procfs_example.c, so: thank - * you, Erik! He can be reached via email at + * This driver is a modified version of Erik Mouw's example proc + * interface, so: thank you, Erik! He can be reached via email at * . It is based on an idea * provided by DEC^WCompaq^WIntel's "Jumpstart" CD. They * included a patch like this as well. Thanks for idea! diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S index 6acea1f96de394d05ef0e13dbea2a29d85a7e0ee..e534e1c5bc11302327ba04825f906c3060bfb2e1 100644 --- a/arch/alpha/kernel/systbls.S +++ b/arch/alpha/kernel/systbls.S @@ -520,6 +520,8 @@ sys_call_table: .quad sys_clock_adjtime .quad sys_syncfs /* 500 */ .quad sys_setns + .quad sys_accept4 + .quad sys_sendmmsg .size sys_call_table, . - sys_call_table .type sys_call_table, @object diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 3146ed3f6eca01a42068454e31f53a3330cc12c6..fe6b0526b3a6fb3f52d35730b84930932050d8a9 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -3,7 +3,7 @@ config ARM default y select HAVE_AOUT select HAVE_DMA_API_DEBUG - select HAVE_IDE + select HAVE_IDE if PCI || ISA || PCMCIA select HAVE_MEMBLOCK select RTC_LIB select SYS_SUPPORTS_APM_EMULATION @@ -29,6 +29,7 @@ config ARM select HAVE_GENERIC_HARDIRQS select HAVE_SPARSE_IRQ select GENERIC_IRQ_SHOW + select CPU_PM if (SUSPEND || CPU_IDLE) help The ARM series is a line of low-power-consumption RISC chip designs licensed by ARM Ltd and targeted at embedded applications and @@ -195,7 +196,8 @@ config VECTORS_BASE The base address of exception vectors. config ARM_PATCH_PHYS_VIRT - bool "Patch physical to virtual translations at runtime" + bool "Patch physical to virtual translations at runtime" if EMBEDDED + default y depends on !XIP_KERNEL && MMU depends on !ARCH_REALVIEW || !SPARSEMEM help @@ -204,16 +206,29 @@ config ARM_PATCH_PHYS_VIRT kernel in system memory. This can only be used with non-XIP MMU kernels where the base - of physical memory is at a 16MB boundary, or theoretically 64K - for the MSM machine class. + of physical memory is at a 16MB boundary. -config ARM_PATCH_PHYS_VIRT_16BIT - def_bool y - depends on ARM_PATCH_PHYS_VIRT && ARCH_MSM + Only disable this option if you know that you do not require + this feature (eg, building a kernel for a single machine) and + you need to shrink the kernel to the minimal size. + +config NEED_MACH_MEMORY_H + bool + help + Select this when mach/memory.h is required to provide special + definitions for this platform. The need for mach/memory.h should + be avoided when possible. + +config PHYS_OFFSET + hex "Physical address of main memory" + depends on !ARM_PATCH_PHYS_VIRT && !NEED_MACH_MEMORY_H help - This option extends the physical to virtual translation patching - to allow physical memory down to a theoretical minimum of 64K - boundaries. + Please provide the physical address corresponding to the + location of main memory in your system. + +config GENERIC_BUG + def_bool y + depends on BUG source "init/Kconfig" @@ -246,6 +261,7 @@ config ARCH_INTEGRATOR select GENERIC_CLOCKEVENTS select PLAT_VERSATILE select PLAT_VERSATILE_FPGA_IRQ + select NEED_MACH_MEMORY_H help Support for ARM's Integrator platform. @@ -261,6 +277,7 @@ config ARCH_REALVIEW select PLAT_VERSATILE_CLCD select ARM_TIMER_SP804 select GPIO_PL061 if GPIOLIB + select NEED_MACH_MEMORY_H help This enables support for ARM Ltd RealView boards. @@ -301,7 +318,6 @@ config ARCH_AT91 select ARCH_REQUIRE_GPIOLIB select HAVE_CLK select CLKDEV_LOOKUP - select ARM_PATCH_PHYS_VIRT if MMU help This enables support for systems based on the Atmel AT91RM9200, AT91SAM9 and AT91CAP9 processors. @@ -318,10 +334,25 @@ config ARCH_BCMRING help Support for Broadcom's BCMRing platform. +config ARCH_HIGHBANK + bool "Calxeda Highbank-based" + select ARCH_WANT_OPTIONAL_GPIOLIB + select ARM_AMBA + select ARM_GIC + select ARM_TIMER_SP804 + select CLKDEV_LOOKUP + select CPU_V7 + select GENERIC_CLOCKEVENTS + select HAVE_ARM_SCU + select USE_OF + help + Support for the Calxeda Highbank SoC based boards. + config ARCH_CLPS711X bool "Cirrus Logic CLPS711x/EP721x-based" select CPU_ARM720T select ARCH_USES_GETTIMEOFFSET + select NEED_MACH_MEMORY_H help Support for Cirrus Logic 711x/721x based boards. @@ -346,7 +377,6 @@ config ARCH_GEMINI config ARCH_PRIMA2 bool "CSR SiRFSoC PRIMA2 ARM Cortex A9 Platform" select CPU_V7 - select GENERIC_TIME select NO_IOPORT select GENERIC_CLOCKEVENTS select CLKDEV_LOOKUP @@ -362,6 +392,7 @@ config ARCH_EBSA110 select ISA select NO_IOPORT select ARCH_USES_GETTIMEOFFSET + select NEED_MACH_MEMORY_H help This is an evaluation board for the StrongARM processor available from Digital. It has limited hardware on-board, including an @@ -377,6 +408,7 @@ config ARCH_EP93XX select ARCH_REQUIRE_GPIOLIB select ARCH_HAS_HOLES_MEMORYMODEL select ARCH_USES_GETTIMEOFFSET + select NEED_MACH_MEMORY_H help This enables support for the Cirrus EP93xx series of CPUs. @@ -385,6 +417,8 @@ config ARCH_FOOTBRIDGE select CPU_SA110 select FOOTBRIDGE select GENERIC_CLOCKEVENTS + select HAVE_IDE + select NEED_MACH_MEMORY_H help Support for systems based on the DC21285 companion chip ("FootBridge"), such as the Simtec CATS and the Rebel NetWinder. @@ -397,6 +431,7 @@ config ARCH_MXC select CLKSRC_MMIO select GENERIC_IRQ_CHIP select HAVE_SCHED_CLOCK + select MULTI_IRQ_HANDLER help Support for Freescale MXC/iMX-based family of processors @@ -434,6 +469,7 @@ config ARCH_IOP13XX select PCI select ARCH_SUPPORTS_MSI select VMSPLIT_1G + select NEED_MACH_MEMORY_H help Support for Intel's IOP13XX (XScale) family of processors. @@ -464,6 +500,7 @@ config ARCH_IXP23XX select CPU_XSC3 select PCI select ARCH_USES_GETTIMEOFFSET + select NEED_MACH_MEMORY_H help Support for Intel's IXP23xx (XScale) family of processors. @@ -473,6 +510,7 @@ config ARCH_IXP2000 select CPU_XSCALE select PCI select ARCH_USES_GETTIMEOFFSET + select NEED_MACH_MEMORY_H help Support for Intel's IXP2400/2800 (XScale) family of processors. @@ -519,7 +557,6 @@ config ARCH_LPC32XX select ARM_AMBA select USB_ARCH_HAS_OHCI select CLKDEV_LOOKUP - select GENERIC_TIME select GENERIC_CLOCKEVENTS help Support for the NXP LPC32XX family of processors @@ -566,6 +603,7 @@ config ARCH_KS8695 select CPU_ARM922T select ARCH_REQUIRE_GPIOLIB select ARCH_USES_GETTIMEOFFSET + select NEED_MACH_MEMORY_H help Support for Micrel/Kendin KS8695 "Centaur" (ARM922T) based System-on-Chip devices. @@ -586,19 +624,10 @@ config ARCH_W90X900 -config ARCH_NUC93X - bool "Nuvoton NUC93X CPU" - select CPU_ARM926T - select CLKDEV_LOOKUP - help - Support for Nuvoton (Winbond logic dept.) NUC93X MCU,The NUC93X is a - low-power and high performance MPEG-4/JPEG multimedia controller chip. - config ARCH_TEGRA bool "NVIDIA Tegra" select CLKDEV_LOOKUP select CLKSRC_MMIO - select GENERIC_TIME select GENERIC_CLOCKEVENTS select GENERIC_GPIO select HAVE_CLK @@ -608,6 +637,24 @@ config ARCH_TEGRA This enables support for NVIDIA Tegra based systems (Tegra APX, Tegra 6xx and Tegra 2 series). +config ARCH_PICOXCELL + bool "Picochip picoXcell" + select ARCH_REQUIRE_GPIOLIB + select ARM_PATCH_PHYS_VIRT + select ARM_VIC + select CPU_V6K + select DW_APB_TIMER + select GENERIC_CLOCKEVENTS + select GENERIC_GPIO + select HAVE_SCHED_CLOCK + select HAVE_TCM + select NO_IOPORT + select USE_OF + help + This enables support for systems based on the Picochip picoXcell + family of Femtocell devices. The picoxcell support requires device tree + for all boards. + config ARCH_PNX4008 bool "Philips Nexperia PNX4008 Mobile" select CPU_ARM926T @@ -631,6 +678,8 @@ config ARCH_PXA select SPARSE_IRQ select AUTO_ZRELADDR select MULTI_IRQ_HANDLER + select ARM_CPU_SUSPEND if PM + select HAVE_IDE help Support for Intel/Marvell's PXA2xx/PXA3xx processor line. @@ -657,6 +706,7 @@ config ARCH_SHMOBILE select SPARSE_IRQ select MULTI_IRQ_HANDLER select PM_GENERIC_DOMAINS if PM + select NEED_MACH_MEMORY_H help Support for Renesas's SH-Mobile and R-Mobile ARM platforms. @@ -671,6 +721,8 @@ config ARCH_RPC select NO_IOPORT select ARCH_SPARSEMEM_ENABLE select ARCH_USES_GETTIMEOFFSET + select HAVE_IDE + select NEED_MACH_MEMORY_H help On the Acorn Risc-PC, Linux can support the internal IDE disk and CD-ROM interface, serial and parallel port, and the floppy drive. @@ -689,6 +741,8 @@ config ARCH_SA1100 select HAVE_SCHED_CLOCK select TICK_ONESHOT select ARCH_REQUIRE_GPIOLIB + select HAVE_IDE + select NEED_MACH_MEMORY_H help Support for StrongARM 11x0 based boards. @@ -722,7 +776,6 @@ config ARCH_S3C64XX select ARCH_REQUIRE_GPIOLIB select SAMSUNG_CLKSRC select SAMSUNG_IRQ_VIC_TIMER - select SAMSUNG_IRQ_UART select S3C_GPIO_TRACK select S3C_GPIO_PULL_UPDOWN select S3C_GPIO_CFG_S3C24XX @@ -781,6 +834,7 @@ config ARCH_S5PV210 select HAVE_S3C2410_I2C if I2C select HAVE_S3C_RTC if RTC_CLASS select HAVE_S3C2410_WATCHDOG if WATCHDOG + select NEED_MACH_MEMORY_H help Samsung S5PV210/S5PC110 series based systems @@ -797,6 +851,7 @@ config ARCH_EXYNOS4 select HAVE_S3C_RTC if RTC_CLASS select HAVE_S3C2410_I2C if I2C select HAVE_S3C2410_WATCHDOG if WATCHDOG + select NEED_MACH_MEMORY_H help Samsung EXYNOS4 series based systems @@ -808,6 +863,7 @@ config ARCH_SHARK select ZONE_DMA select PCI select ARCH_USES_GETTIMEOFFSET + select NEED_MACH_MEMORY_H help Support for the StrongARM based Digital DNARD machine, also known as "Shark" (). @@ -830,11 +886,14 @@ config ARCH_U300 select HAVE_SCHED_CLOCK select HAVE_TCM select ARM_AMBA + select ARM_PATCH_PHYS_VIRT select ARM_VIC select GENERIC_CLOCKEVENTS select CLKDEV_LOOKUP select HAVE_MACH_CLKDEV select GENERIC_GPIO + select ARCH_REQUIRE_GPIOLIB + select NEED_MACH_MEMORY_H help Support for ST-Ericsson U300 series mobile platforms. @@ -910,7 +969,6 @@ config ARCH_VT8500 config ARCH_ZYNQ bool "Xilinx Zynq ARM Cortex A9 Platform" select CPU_V7 - select GENERIC_TIME select GENERIC_CLOCKEVENTS select CLKDEV_LOOKUP select ARM_GIC @@ -979,8 +1037,6 @@ source "arch/arm/mach-netx/Kconfig" source "arch/arm/mach-nomadik/Kconfig" source "arch/arm/plat-nomadik/Kconfig" -source "arch/arm/mach-nuc93x/Kconfig" - source "arch/arm/plat-omap/Kconfig" source "arch/arm/mach-omap1/Kconfig" @@ -1374,7 +1430,8 @@ config SMP depends on REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP || \ MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \ ARCH_EXYNOS4 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || \ - ARCH_MSM_SCORPIONMP || ARCH_SHMOBILE + ARCH_MSM_SCORPIONMP || ARCH_SHMOBILE || ARCH_HIGHBANK || SOC_IMX6Q + depends on MMU select USE_GENERIC_SMP_HELPERS select HAVE_ARM_SCU if !ARCH_MSM_SCORPIONMP help @@ -1388,7 +1445,7 @@ config SMP processor machines. On a single processor machine, the kernel will run faster if you say N here. - See also , + See also , and the SMP-HOWTO available at . @@ -1407,6 +1464,31 @@ config SMP_ON_UP If you don't know what to do here, say Y. +config ARM_CPU_TOPOLOGY + bool "Support cpu topology definition" + depends on SMP && CPU_V7 + default y + help + Support ARM cpu topology definition. The MPIDR register defines + affinity between processors which is then used to describe the cpu + topology of an ARM System. + +config SCHED_MC + bool "Multi-core scheduler support" + depends on ARM_CPU_TOPOLOGY + help + Multi-core scheduler support improves the CPU scheduler's decision + making when dealing with multi-core CPU chips at a cost of slightly + increased overhead in some places. If unsure say N here. + +config SCHED_SMT + bool "SMT scheduler support" + depends on ARM_CPU_TOPOLOGY + help + Improves the CPU scheduler's decision making when dealing with + MultiThreading at a cost of slightly increased overhead in some + places. If unsure say N here. + config HAVE_ARM_SCU bool help @@ -1482,6 +1564,7 @@ config THUMB2_KERNEL depends on CPU_V7 && !CPU_V6 && !CPU_V6K && EXPERIMENTAL select AEABI select ARM_ASM_UNIFIED + select ARM_UNWIND help By enabling this option, the kernel will be compiled in Thumb-2 mode. A compiler/assembler that understand the unified @@ -1807,6 +1890,38 @@ config ZBOOT_ROM_SH_MOBILE_SDHI endchoice +config ARM_APPENDED_DTB + bool "Use appended device tree blob to zImage (EXPERIMENTAL)" + depends on OF && !ZBOOT_ROM && EXPERIMENTAL + help + With this option, the boot code will look for a device tree binary + (DTB) appended to zImage + (e.g. cat zImage .dtb > zImage_w_dtb). + + This is meant as a backward compatibility convenience for those + systems with a bootloader that can't be upgraded to accommodate + the documented boot protocol using a device tree. + + Beware that there is very little in terms of protection against + this option being confused by leftover garbage in memory that might + look like a DTB header after a reboot if no actual DTB is appended + to zImage. Do not leave this option active in a production kernel + if you don't intend to always append a DTB. Proper passing of the + location into r2 of a bootloader provided DTB is always preferable + to this option. + +config ARM_ATAG_DTB_COMPAT + bool "Supplement the appended DTB with traditional ATAG information" + depends on ARM_APPENDED_DTB + help + Some old bootloaders can't be updated to a DTB capable one, yet + they provide ATAGs with memory configuration, the ramdisk address, + the kernel cmdline string, etc. Such information is dynamically + provided by the bootloader and can't always be stored in a static + DTB. To allow a device tree enabled kernel to be used with such + bootloaders, this option allows zImage to extract the information + from the ATAG list and store it at run time into the appended DTB. + config CMDLINE string "Default kernel command string" default "" @@ -1953,6 +2068,7 @@ config CPU_FREQ_PXA bool depends on CPU_FREQ && ARCH_PXA && PXA25x default y + select CPU_FREQ_TABLE select CPU_FREQ_DEFAULT_GOV_USERSPACE config CPU_FREQ_S3C @@ -2101,6 +2217,9 @@ config ARCH_SUSPEND_POSSIBLE CPU_V6 || CPU_V6K || CPU_V7 || CPU_XSC3 || CPU_XSCALE def_bool y +config ARM_CPU_SUSPEND + def_bool PM_SLEEP + endmenu source "net/Kconfig" diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 81cbe40c159c63c20968d224f960d3d353509946..c5213e78606b15efd4d9454dff34c674b6ff276b 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -65,13 +65,190 @@ config DEBUG_USER # These options are only for real kernel hackers who want to get their hands dirty. config DEBUG_LL - bool "Kernel low-level debugging functions" + bool "Kernel low-level debugging functions (read help!)" depends on DEBUG_KERNEL help Say Y here to include definitions of printascii, printch, printhex in the kernel. This is helpful if you are debugging code that executes before the console is initialized. + Note that selecting this option will limit the kernel to a single + UART definition, as specified below. Attempting to boot the kernel + image on a different platform *will not work*, so this option should + not be enabled for kernels that are intended to be portable. + +choice + prompt "Kernel low-level debugging port" + depends on DEBUG_LL + + config DEBUG_LL_UART_NONE + bool "No low-level debugging UART" + help + Say Y here if your platform doesn't provide a UART option + below. This relies on your platform choosing the right UART + definition internally in order for low-level debugging to + work. + + config DEBUG_ICEDCC + bool "Kernel low-level debugging via EmbeddedICE DCC channel" + help + Say Y here if you want the debug print routines to direct + their output to the EmbeddedICE macrocell's DCC channel using + co-processor 14. This is known to work on the ARM9 style ICE + channel and on the XScale with the PEEDI. + + Note that the system will appear to hang during boot if there + is nothing connected to read from the DCC. + + config DEBUG_FOOTBRIDGE_COM1 + bool "Kernel low-level debugging messages via footbridge 8250 at PCI COM1" + depends on FOOTBRIDGE + help + Say Y here if you want the debug print routines to direct + their output to the 8250 at PCI COM1. + + config DEBUG_DC21285_PORT + bool "Kernel low-level debugging messages via footbridge serial port" + depends on FOOTBRIDGE + help + Say Y here if you want the debug print routines to direct + their output to the serial port in the DC21285 (Footbridge). + + config DEBUG_CLPS711X_UART1 + bool "Kernel low-level debugging messages via UART1" + depends on ARCH_CLPS711X + help + Say Y here if you want the debug print routines to direct + their output to the first serial port on these devices. + + config DEBUG_CLPS711X_UART2 + bool "Kernel low-level debugging messages via UART2" + depends on ARCH_CLPS711X + help + Say Y here if you want the debug print routines to direct + their output to the second serial port on these devices. + + config DEBUG_HIGHBANK_UART + bool "Kernel low-level debugging messages via Highbank UART" + depends on ARCH_HIGHBANK + help + Say Y here if you want the debug print routines to direct + their output to the UART on Highbank based devices. + + config DEBUG_IMX1_UART + bool "i.MX1 Debug UART" + depends on SOC_IMX1 + help + Say Y here if you want kernel low-level debugging support + on i.MX1. + + config DEBUG_IMX23_UART + bool "i.MX23 Debug UART" + depends on SOC_IMX23 + help + Say Y here if you want kernel low-level debugging support + on i.MX23. + + config DEBUG_IMX25_UART + bool "i.MX25 Debug UART" + depends on SOC_IMX25 + help + Say Y here if you want kernel low-level debugging support + on i.MX25. + + config DEBUG_IMX21_IMX27_UART + bool "i.MX21 and i.MX27 Debug UART" + depends on SOC_IMX21 || SOC_IMX27 + help + Say Y here if you want kernel low-level debugging support + on i.MX21 or i.MX27. + + config DEBUG_IMX28_UART + bool "i.MX28 Debug UART" + depends on SOC_IMX28 + help + Say Y here if you want kernel low-level debugging support + on i.MX28. + + config DEBUG_IMX31_IMX35_UART + bool "i.MX31 and i.MX35 Debug UART" + depends on SOC_IMX31 || SOC_IMX35 + help + Say Y here if you want kernel low-level debugging support + on i.MX31 or i.MX35. + + config DEBUG_IMX51_UART + bool "i.MX51 Debug UART" + depends on SOC_IMX51 + help + Say Y here if you want kernel low-level debugging support + on i.MX51. + + config DEBUG_IMX50_IMX53_UART + bool "i.MX50 and i.MX53 Debug UART" + depends on SOC_IMX50 || SOC_IMX53 + help + Say Y here if you want kernel low-level debugging support + on i.MX50 or i.MX53. + + config DEBUG_IMX6Q_UART + bool "i.MX6Q Debug UART" + depends on SOC_IMX6Q + help + Say Y here if you want kernel low-level debugging support + on i.MX6Q. + + config DEBUG_S3C_UART0 + depends on PLAT_SAMSUNG + bool "Use S3C UART 0 for low-level debug" + help + Say Y here if you want the debug print routines to direct + their output to UART 0. The port must have been initialised + by the boot-loader before use. + + The uncompressor code port configuration is now handled + by CONFIG_S3C_LOWLEVEL_UART_PORT. + + config DEBUG_S3C_UART1 + depends on PLAT_SAMSUNG + bool "Use S3C UART 1 for low-level debug" + help + Say Y here if you want the debug print routines to direct + their output to UART 1. The port must have been initialised + by the boot-loader before use. + + The uncompressor code port configuration is now handled + by CONFIG_S3C_LOWLEVEL_UART_PORT. + + config DEBUG_S3C_UART2 + depends on PLAT_SAMSUNG + bool "Use S3C UART 2 for low-level debug" + help + Say Y here if you want the debug print routines to direct + their output to UART 2. The port must have been initialised + by the boot-loader before use. + + The uncompressor code port configuration is now handled + by CONFIG_S3C_LOWLEVEL_UART_PORT. + + config DEBUG_REALVIEW_STD_PORT + bool "RealView Default UART" + depends on ARCH_REALVIEW + help + Say Y here if you want the debug print routines to direct + their output to the serial port on RealView EB, PB11MP, PBA8 + and PBX platforms. + + config DEBUG_REALVIEW_PB1176_PORT + bool "RealView PB1176 UART" + depends on MACH_REALVIEW_PB1176 + help + Say Y here if you want the debug print routines to direct + their output to the standard serial port on the RealView + PB1176 platform. + +endchoice + config EARLY_PRINTK bool "Early printk" depends on DEBUG_LL @@ -80,53 +257,18 @@ config EARLY_PRINTK kernel low-level debugging functions. Add earlyprintk to your kernel parameters to enable this console. -config DEBUG_ICEDCC - bool "Kernel low-level debugging via EmbeddedICE DCC channel" - depends on DEBUG_LL - help - Say Y here if you want the debug print routines to direct their - output to the EmbeddedICE macrocell's DCC channel using - co-processor 14. This is known to work on the ARM9 style ICE - channel and on the XScale with the PEEDI. - - It does include a timeout to ensure that the system does not - totally freeze when there is nothing connected to read. - config OC_ETM bool "On-chip ETM and ETB" - select ARM_AMBA + depends on ARM_AMBA help Enables the on-chip embedded trace macrocell and embedded trace buffer driver that will allow you to collect traces of the kernel code. -config DEBUG_DC21285_PORT - bool "Kernel low-level debugging messages via footbridge serial port" - depends on DEBUG_LL && FOOTBRIDGE - help - Say Y here if you want the debug print routines to direct their - output to the serial port in the DC21285 (Footbridge). Saying N - will cause the debug messages to appear on the first 16550 - serial port. - -config DEBUG_CLPS711X_UART2 - bool "Kernel low-level debugging messages via UART2" - depends on DEBUG_LL && ARCH_CLPS711X +config ARM_KPROBES_TEST + tristate "Kprobes test module" + depends on KPROBES && MODULES help - Say Y here if you want the debug print routines to direct their - output to the second serial port on these devices. Saying N will - cause the debug messages to appear on the first serial port. - -config DEBUG_S3C_UART - depends on PLAT_SAMSUNG - int "S3C UART to use for low-level debug" - default "0" - help - Choice for UART for kernel low-level using S3C UARTS, - should be between zero and two. The port must have been - initialised by the boot-loader before use. - - The uncompressor code port configuration is now handled - by CONFIG_S3C_LOWLEVEL_UART_PORT. + Perform tests of kprobes API and instruction set simulation. endmenu diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 70c424eaf7b0d84db6af6431279a835ba71094c2..b7c2d377a6c2330ed194ff931f0a91ec33b0fce8 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -128,6 +128,9 @@ textofs-$(CONFIG_PM_H1940) := 0x00108000 ifeq ($(CONFIG_ARCH_SA1100),y) textofs-$(CONFIG_SA1111) := 0x00208000 endif +textofs-$(CONFIG_ARCH_MSM7X30) := 0x00208000 +textofs-$(CONFIG_ARCH_MSM8X60) := 0x00208000 +textofs-$(CONFIG_ARCH_MSM8960) := 0x00208000 # Machine directory name. This list is sorted alphanumerically # by CONFIG_* macro name. @@ -141,6 +144,7 @@ machine-$(CONFIG_ARCH_EBSA110) := ebsa110 machine-$(CONFIG_ARCH_EP93XX) := ep93xx machine-$(CONFIG_ARCH_GEMINI) := gemini machine-$(CONFIG_ARCH_H720X) := h720x +machine-$(CONFIG_ARCH_HIGHBANK) := highbank machine-$(CONFIG_ARCH_INTEGRATOR) := integrator machine-$(CONFIG_ARCH_IOP13XX) := iop13xx machine-$(CONFIG_ARCH_IOP32X) := iop32x @@ -154,10 +158,8 @@ machine-$(CONFIG_ARCH_LPC32XX) := lpc32xx machine-$(CONFIG_ARCH_MMP) := mmp machine-$(CONFIG_ARCH_MSM) := msm machine-$(CONFIG_ARCH_MV78XX0) := mv78xx0 -machine-$(CONFIG_ARCH_MX1) := imx -machine-$(CONFIG_ARCH_MX2) := imx -machine-$(CONFIG_ARCH_MX25) := imx -machine-$(CONFIG_ARCH_MX3) := imx +machine-$(CONFIG_ARCH_IMX_V4_V5) := imx +machine-$(CONFIG_ARCH_IMX_V6_V7) := imx machine-$(CONFIG_ARCH_MX5) := mx5 machine-$(CONFIG_ARCH_MXS) := mxs machine-$(CONFIG_ARCH_NETX) := netx @@ -167,6 +169,7 @@ machine-$(CONFIG_ARCH_OMAP2) := omap2 machine-$(CONFIG_ARCH_OMAP3) := omap2 machine-$(CONFIG_ARCH_OMAP4) := omap2 machine-$(CONFIG_ARCH_ORION5X) := orion5x +machine-$(CONFIG_ARCH_PICOXCELL) := picoxcell machine-$(CONFIG_ARCH_PNX4008) := pnx4008 machine-$(CONFIG_ARCH_PRIMA2) := prima2 machine-$(CONFIG_ARCH_PXA) := pxa @@ -189,7 +192,6 @@ machine-$(CONFIG_ARCH_VERSATILE) := versatile machine-$(CONFIG_ARCH_VEXPRESS) := vexpress machine-$(CONFIG_ARCH_VT8500) := vt8500 machine-$(CONFIG_ARCH_W90X900) := w90x900 -machine-$(CONFIG_ARCH_NUC93X) := nuc93x machine-$(CONFIG_FOOTBRIDGE) := footbridge machine-$(CONFIG_MACH_SPEAR300) := spear3xx machine-$(CONFIG_MACH_SPEAR310) := spear3xx diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile index a1edfd5a129a653ba847b5fb310a88bacfecfc1d..176062ac7f07305014357372c42285ff07a09c68 100644 --- a/arch/arm/boot/Makefile +++ b/arch/arm/boot/Makefile @@ -78,7 +78,16 @@ endif $(obj)/uImage: STARTADDR=$(LOADADDR) +check_for_multiple_loadaddr = \ +if [ $(words $(LOADADDR)) -gt 1 ]; then \ + echo 'multiple load addresses: $(LOADADDR)'; \ + echo 'This is incompatible with uImages'; \ + echo 'Specify LOADADDR on the commandline to build an uImage'; \ + false; \ +fi + $(obj)/uImage: $(obj)/zImage FORCE + @$(check_for_multiple_loadaddr) $(call if_changed,uimage) @echo ' Image $@ is ready' diff --git a/arch/arm/boot/compressed/.gitignore b/arch/arm/boot/compressed/.gitignore index c6028967d33676215841e056f8b4af7f4832f3b6..e0936a148516e2c5005d3620065938b4acec8b11 100644 --- a/arch/arm/boot/compressed/.gitignore +++ b/arch/arm/boot/compressed/.gitignore @@ -5,3 +5,12 @@ piggy.lzo piggy.lzma vmlinux vmlinux.lds + +# borrowed libfdt files +fdt.c +fdt.h +fdt_ro.c +fdt_rw.c +fdt_wip.c +libfdt.h +libfdt_internal.h diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 0c74a6fab95278eee8cdbc077aa0800c40da428f..21f56ff32797eaef80af79c49db60ce2c89912fa 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -26,6 +26,10 @@ HEAD = head.o OBJS += misc.o decompress.o FONTC = $(srctree)/drivers/video/console/font_acorn_8x8.c +# string library code (-Os is enforced to keep it much smaller) +OBJS += string.o +CFLAGS_string.o := -Os + # # Architecture dependencies # @@ -89,21 +93,41 @@ suffix_$(CONFIG_KERNEL_GZIP) = gzip suffix_$(CONFIG_KERNEL_LZO) = lzo suffix_$(CONFIG_KERNEL_LZMA) = lzma +# Borrowed libfdt files for the ATAG compatibility mode + +libfdt := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c +libfdt_hdrs := fdt.h libfdt.h libfdt_internal.h + +libfdt_objs := $(addsuffix .o, $(basename $(libfdt))) + +$(addprefix $(obj)/,$(libfdt) $(libfdt_hdrs)): $(obj)/%: $(srctree)/scripts/dtc/libfdt/% + $(call cmd,shipped) + +$(addprefix $(obj)/,$(libfdt_objs) atags_to_fdt.o): \ + $(addprefix $(obj)/,$(libfdt_hdrs)) + +ifeq ($(CONFIG_ARM_ATAG_DTB_COMPAT),y) +OBJS += $(libfdt_objs) atags_to_fdt.o +endif + targets := vmlinux vmlinux.lds \ piggy.$(suffix_y) piggy.$(suffix_y).o \ - font.o font.c head.o misc.o $(OBJS) + lib1funcs.o lib1funcs.S font.o font.c head.o misc.o $(OBJS) # Make sure files are removed during clean -extra-y += piggy.gzip piggy.lzo piggy.lzma lib1funcs.S +extra-y += piggy.gzip piggy.lzo piggy.lzma lib1funcs.S $(libfdt) $(libfdt_hdrs) ifeq ($(CONFIG_FUNCTION_TRACER),y) ORIG_CFLAGS := $(KBUILD_CFLAGS) KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS)) endif -ccflags-y := -fpic -fno-builtin +ccflags-y := -fpic -fno-builtin -I$(obj) asflags-y := -Wa,-march=all +# Supply kernel BSS size to the decompressor via a linker symbol. +KBSS_SZ = $(shell size $(obj)/../../../../vmlinux | awk 'END{print $$3}') +LDFLAGS_vmlinux = --defsym _kernel_bss_size=$(KBSS_SZ) # Supply ZRELADDR to the decompressor via a linker symbol. ifneq ($(CONFIG_AUTO_ZRELADDR),y) LDFLAGS_vmlinux += --defsym zreladdr=$(ZRELADDR) @@ -123,7 +147,7 @@ LDFLAGS_vmlinux += -T # For __aeabi_uidivmod lib1funcs = $(obj)/lib1funcs.o -$(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S FORCE +$(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S $(call cmd,shipped) # We need to prevent any GOTOFF relocs being used with references @@ -139,8 +163,16 @@ bad_syms=$$($(CROSS_COMPILE)nm $@ | sed -n 's/^.\{8\} [bc] \(.*\)/\1/p') && \ ( echo "following symbols must have non local/private scope:" >&2; \ echo "$$bad_syms" >&2; rm -f $@; false ) +check_for_multiple_zreladdr = \ +if [ $(words $(ZRELADDR)) -gt 1 -a "$(CONFIG_AUTO_ZRELADDR)" = "" ]; then \ + echo 'multiple zreladdrs: $(ZRELADDR)'; \ + echo 'This needs CONFIG_AUTO_ZRELADDR to be set'; \ + false; \ +fi + $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \ $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE + @$(check_for_multiple_zreladdr) $(call if_changed,ld) @$(check_for_bad_syms) diff --git a/arch/arm/boot/compressed/atags_to_fdt.c b/arch/arm/boot/compressed/atags_to_fdt.c new file mode 100644 index 0000000000000000000000000000000000000000..6ce11c4811786389b830d497814c5338983cc723 --- /dev/null +++ b/arch/arm/boot/compressed/atags_to_fdt.c @@ -0,0 +1,97 @@ +#include +#include + +static int node_offset(void *fdt, const char *node_path) +{ + int offset = fdt_path_offset(fdt, node_path); + if (offset == -FDT_ERR_NOTFOUND) + offset = fdt_add_subnode(fdt, 0, node_path); + return offset; +} + +static int setprop(void *fdt, const char *node_path, const char *property, + uint32_t *val_array, int size) +{ + int offset = node_offset(fdt, node_path); + if (offset < 0) + return offset; + return fdt_setprop(fdt, offset, property, val_array, size); +} + +static int setprop_string(void *fdt, const char *node_path, + const char *property, const char *string) +{ + int offset = node_offset(fdt, node_path); + if (offset < 0) + return offset; + return fdt_setprop_string(fdt, offset, property, string); +} + +static int setprop_cell(void *fdt, const char *node_path, + const char *property, uint32_t val) +{ + int offset = node_offset(fdt, node_path); + if (offset < 0) + return offset; + return fdt_setprop_cell(fdt, offset, property, val); +} + +/* + * Convert and fold provided ATAGs into the provided FDT. + * + * REturn values: + * = 0 -> pretend success + * = 1 -> bad ATAG (may retry with another possible ATAG pointer) + * < 0 -> error from libfdt + */ +int atags_to_fdt(void *atag_list, void *fdt, int total_space) +{ + struct tag *atag = atag_list; + uint32_t mem_reg_property[2 * NR_BANKS]; + int memcount = 0; + int ret; + + /* make sure we've got an aligned pointer */ + if ((u32)atag_list & 0x3) + return 1; + + /* if we get a DTB here we're done already */ + if (*(u32 *)atag_list == fdt32_to_cpu(FDT_MAGIC)) + return 0; + + /* validate the ATAG */ + if (atag->hdr.tag != ATAG_CORE || + (atag->hdr.size != tag_size(tag_core) && + atag->hdr.size != 2)) + return 1; + + /* let's give it all the room it could need */ + ret = fdt_open_into(fdt, fdt, total_space); + if (ret < 0) + return ret; + + for_each_tag(atag, atag_list) { + if (atag->hdr.tag == ATAG_CMDLINE) { + setprop_string(fdt, "/chosen", "bootargs", + atag->u.cmdline.cmdline); + } else if (atag->hdr.tag == ATAG_MEM) { + if (memcount >= sizeof(mem_reg_property)/4) + continue; + mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.start); + mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.size); + } else if (atag->hdr.tag == ATAG_INITRD2) { + uint32_t initrd_start, initrd_size; + initrd_start = atag->u.initrd.start; + initrd_size = atag->u.initrd.size; + setprop_cell(fdt, "/chosen", "linux,initrd-start", + initrd_start); + setprop_cell(fdt, "/chosen", "linux,initrd-end", + initrd_start + initrd_size); + } + } + + if (memcount) + setprop(fdt, "/memory", "reg", mem_reg_property, 4*memcount); + + return fdt_pack(fdt); +} diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index e95a5989602ae3fcf54f56257ce35739593d5f86..c2effc91725452dcaa93af7b3dc1b0ce20d979c2 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -216,6 +216,104 @@ restart: adr r0, LC0 mov r10, r6 #endif + mov r5, #0 @ init dtb size to 0 +#ifdef CONFIG_ARM_APPENDED_DTB +/* + * r0 = delta + * r2 = BSS start + * r3 = BSS end + * r4 = final kernel address + * r5 = appended dtb size (still unknown) + * r6 = _edata + * r7 = architecture ID + * r8 = atags/device tree pointer + * r9 = size of decompressed image + * r10 = end of this image, including bss/stack/malloc space if non XIP + * r11 = GOT start + * r12 = GOT end + * sp = stack pointer + * + * if there are device trees (dtb) appended to zImage, advance r10 so that the + * dtb data will get relocated along with the kernel if necessary. + */ + + ldr lr, [r6, #0] +#ifndef __ARMEB__ + ldr r1, =0xedfe0dd0 @ sig is 0xd00dfeed big endian +#else + ldr r1, =0xd00dfeed +#endif + cmp lr, r1 + bne dtb_check_done @ not found + +#ifdef CONFIG_ARM_ATAG_DTB_COMPAT + /* + * OK... Let's do some funky business here. + * If we do have a DTB appended to zImage, and we do have + * an ATAG list around, we want the later to be translated + * and folded into the former here. To be on the safe side, + * let's temporarily move the stack away into the malloc + * area. No GOT fixup has occurred yet, but none of the + * code we're about to call uses any global variable. + */ + add sp, sp, #0x10000 + stmfd sp!, {r0-r3, ip, lr} + mov r0, r8 + mov r1, r6 + sub r2, sp, r6 + bl atags_to_fdt + + /* + * If returned value is 1, there is no ATAG at the location + * pointed by r8. Try the typical 0x100 offset from start + * of RAM and hope for the best. + */ + cmp r0, #1 + sub r0, r4, #TEXT_OFFSET + add r0, r0, #0x100 + mov r1, r6 + sub r2, sp, r6 + blne atags_to_fdt + + ldmfd sp!, {r0-r3, ip, lr} + sub sp, sp, #0x10000 +#endif + + mov r8, r6 @ use the appended device tree + + /* + * Make sure that the DTB doesn't end up in the final + * kernel's .bss area. To do so, we adjust the decompressed + * kernel size to compensate if that .bss size is larger + * than the relocated code. + */ + ldr r5, =_kernel_bss_size + adr r1, wont_overwrite + sub r1, r6, r1 + subs r1, r5, r1 + addhi r9, r9, r1 + + /* Get the dtb's size */ + ldr r5, [r6, #4] +#ifndef __ARMEB__ + /* convert r5 (dtb size) to little endian */ + eor r1, r5, r5, ror #16 + bic r1, r1, #0x00ff0000 + mov r5, r5, ror #8 + eor r5, r5, r1, lsr #8 +#endif + + /* preserve 64-bit alignment */ + add r5, r5, #7 + bic r5, r5, #7 + + /* relocate some pointers past the appended dtb */ + add r6, r6, r5 + add r10, r10, r5 + add sp, sp, r5 +dtb_check_done: +#endif + /* * Check to see if we will overwrite ourselves. * r4 = final kernel address @@ -223,15 +321,14 @@ restart: adr r0, LC0 * r10 = end of this image, including bss/stack/malloc space if non XIP * We basically want: * r4 - 16k page directory >= r10 -> OK - * r4 + image length <= current position (pc) -> OK + * r4 + image length <= address of wont_overwrite -> OK */ add r10, r10, #16384 cmp r4, r10 bhs wont_overwrite add r10, r4, r9 - ARM( cmp r10, pc ) - THUMB( mov lr, pc ) - THUMB( cmp r10, lr ) + adr r9, wont_overwrite + cmp r10, r9 bls wont_overwrite /* @@ -285,14 +382,16 @@ wont_overwrite: * r2 = BSS start * r3 = BSS end * r4 = kernel execution address + * r5 = appended dtb size (0 if not present) * r7 = architecture ID * r8 = atags pointer * r11 = GOT start * r12 = GOT end * sp = stack pointer */ - teq r0, #0 + orrs r1, r0, r5 beq not_relocated + add r11, r11, r0 add r12, r12, r0 @@ -307,12 +406,21 @@ wont_overwrite: /* * Relocate all entries in the GOT table. + * Bump bss entries to _edata + dtb size */ 1: ldr r1, [r11, #0] @ relocate entries in the GOT - add r1, r1, r0 @ table. This fixes up the - str r1, [r11], #4 @ C references. + add r1, r1, r0 @ This fixes up C references + cmp r1, r2 @ if entry >= bss_start && + cmphs r3, r1 @ bss_end > entry + addhi r1, r1, r5 @ entry += dtb size + str r1, [r11], #4 @ next entry cmp r11, r12 blo 1b + + /* bump our bss pointers too */ + add r2, r2, r5 + add r3, r3, r5 + #else /* diff --git a/arch/arm/boot/compressed/libfdt_env.h b/arch/arm/boot/compressed/libfdt_env.h new file mode 100644 index 0000000000000000000000000000000000000000..1f4e71876b00a0719c57b40ff9805accbb1f45bd --- /dev/null +++ b/arch/arm/boot/compressed/libfdt_env.h @@ -0,0 +1,15 @@ +#ifndef _ARM_LIBFDT_ENV_H +#define _ARM_LIBFDT_ENV_H + +#include +#include +#include + +#define fdt16_to_cpu(x) be16_to_cpu(x) +#define cpu_to_fdt16(x) cpu_to_be16(x) +#define fdt32_to_cpu(x) be32_to_cpu(x) +#define cpu_to_fdt32(x) cpu_to_be32(x) +#define fdt64_to_cpu(x) be64_to_cpu(x) +#define cpu_to_fdt64(x) cpu_to_be64(x) + +#endif diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c index 832d37236c59fdc92c852166d64a6b0c6efc71d5..8e2a8fca5ed205bcbfda7faafa1eb0d7628a863b 100644 --- a/arch/arm/boot/compressed/misc.c +++ b/arch/arm/boot/compressed/misc.c @@ -18,14 +18,9 @@ unsigned int __machine_arch_type; -#define _LINUX_STRING_H_ - #include /* for inline */ -#include /* for size_t */ -#include /* for NULL */ +#include #include -#include - static void putstr(const char *ptr); extern void error(char *x); @@ -101,41 +96,6 @@ static void putstr(const char *ptr) flush(); } - -void *memcpy(void *__dest, __const void *__src, size_t __n) -{ - int i = 0; - unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src; - - for (i = __n >> 3; i > 0; i--) { - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - } - - if (__n & 1 << 2) { - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - } - - if (__n & 1 << 1) { - *d++ = *s++; - *d++ = *s++; - } - - if (__n & 1) - *d++ = *s++; - - return __dest; -} - /* * gzip declarations */ diff --git a/arch/arm/boot/compressed/string.c b/arch/arm/boot/compressed/string.c new file mode 100644 index 0000000000000000000000000000000000000000..36e53ef9200f236d7ad2c5e8cdcb9b7b372f0aa3 --- /dev/null +++ b/arch/arm/boot/compressed/string.c @@ -0,0 +1,127 @@ +/* + * arch/arm/boot/compressed/string.c + * + * Small subset of simple string routines + */ + +#include + +void *memcpy(void *__dest, __const void *__src, size_t __n) +{ + int i = 0; + unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src; + + for (i = __n >> 3; i > 0; i--) { + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + } + + if (__n & 1 << 2) { + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + } + + if (__n & 1 << 1) { + *d++ = *s++; + *d++ = *s++; + } + + if (__n & 1) + *d++ = *s++; + + return __dest; +} + +void *memmove(void *__dest, __const void *__src, size_t count) +{ + unsigned char *d = __dest; + const unsigned char *s = __src; + + if (__dest == __src) + return __dest; + + if (__dest < __src) + return memcpy(__dest, __src, count); + + while (count--) + d[count] = s[count]; + return __dest; +} + +size_t strlen(const char *s) +{ + const char *sc = s; + + while (*sc != '\0') + sc++; + return sc - s; +} + +int memcmp(const void *cs, const void *ct, size_t count) +{ + const unsigned char *su1 = cs, *su2 = ct, *end = su1 + count; + int res = 0; + + while (su1 < end) { + res = *su1++ - *su2++; + if (res) + break; + } + return res; +} + +int strcmp(const char *cs, const char *ct) +{ + unsigned char c1, c2; + int res = 0; + + do { + c1 = *cs++; + c2 = *ct++; + res = c1 - c2; + if (res) + break; + } while (c1); + return res; +} + +void *memchr(const void *s, int c, size_t count) +{ + const unsigned char *p = s; + + while (count--) + if ((unsigned char)c == *p++) + return (void *)(p - 1); + return NULL; +} + +char *strchr(const char *s, int c) +{ + while (*s != (char)c) + if (*s++ == '\0') + return NULL; + return (char *)s; +} + +#undef memset + +void *memset(void *s, int c, size_t count) +{ + char *xs = s; + while (count--) + *xs++ = c; + return s; +} + +void __memzero(void *s, size_t count) +{ + memset(s, 0, count); +} diff --git a/arch/arm/boot/compressed/vmlinux.lds.in b/arch/arm/boot/compressed/vmlinux.lds.in index 4e728834a1b9dea2d0d6a41076d9a3d572424321..4919f2ac8b89709a6cd3929603b1f3fc401293c5 100644 --- a/arch/arm/boot/compressed/vmlinux.lds.in +++ b/arch/arm/boot/compressed/vmlinux.lds.in @@ -51,6 +51,10 @@ SECTIONS _got_start = .; .got : { *(.got) } _got_end = .; + + /* ensure the zImage file size is always a multiple of 64 bits */ + /* (without a dummy byte, ld just ignores the empty section) */ + .pad : { BYTE(0); . = ALIGN(8); } _edata = .; . = BSS_START; diff --git a/arch/arm/boot/dts/at91sam9g20.dtsi b/arch/arm/boot/dts/at91sam9g20.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..aeef04269cf85edfb1259de7c64453b1bfb2e843 --- /dev/null +++ b/arch/arm/boot/dts/at91sam9g20.dtsi @@ -0,0 +1,119 @@ +/* + * at91sam9g20.dtsi - Device Tree Include file for AT91SAM9G20 family SoC + * + * Copyright (C) 2011 Atmel, + * 2011 Nicolas Ferre , + * 2011 Jean-Christophe PLAGNIOL-VILLARD + * + * Licensed under GPLv2 or later. + */ + +/include/ "skeleton.dtsi" + +/ { + model = "Atmel AT91SAM9G20 family SoC"; + compatible = "atmel,at91sam9g20"; + interrupt-parent = <&aic>; + + aliases { + serial0 = &dbgu; + serial1 = &usart0; + serial2 = &usart1; + serial3 = &usart2; + serial4 = &usart3; + serial5 = &usart4; + serial6 = &usart5; + }; + cpus { + cpu@0 { + compatible = "arm,arm926ejs"; + }; + }; + + memory@20000000 { + reg = <0x20000000 0x08000000>; + }; + + ahb { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + apb { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + aic: interrupt-controller@fffff000 { + #interrupt-cells = <1>; + compatible = "atmel,at91rm9200-aic"; + interrupt-controller; + interrupt-parent; + reg = <0xfffff000 0x200>; + }; + + dbgu: serial@fffff200 { + compatible = "atmel,at91sam9260-usart"; + reg = <0xfffff200 0x200>; + interrupts = <1>; + status = "disabled"; + }; + + usart0: serial@fffb0000 { + compatible = "atmel,at91sam9260-usart"; + reg = <0xfffb0000 0x200>; + interrupts = <6>; + atmel,use-dma-rx; + atmel,use-dma-tx; + status = "disabled"; + }; + + usart1: serial@fffb4000 { + compatible = "atmel,at91sam9260-usart"; + reg = <0xfffb4000 0x200>; + interrupts = <7>; + atmel,use-dma-rx; + atmel,use-dma-tx; + status = "disabled"; + }; + + usart2: serial@fffb8000 { + compatible = "atmel,at91sam9260-usart"; + reg = <0xfffb8000 0x200>; + interrupts = <8>; + atmel,use-dma-rx; + atmel,use-dma-tx; + status = "disabled"; + }; + + usart3: serial@fffd0000 { + compatible = "atmel,at91sam9260-usart"; + reg = <0xfffd0000 0x200>; + interrupts = <23>; + atmel,use-dma-rx; + atmel,use-dma-tx; + status = "disabled"; + }; + + usart4: serial@fffd4000 { + compatible = "atmel,at91sam9260-usart"; + reg = <0xfffd4000 0x200>; + interrupts = <24>; + atmel,use-dma-rx; + atmel,use-dma-tx; + status = "disabled"; + }; + + usart5: serial@fffd8000 { + compatible = "atmel,at91sam9260-usart"; + reg = <0xfffd8000 0x200>; + interrupts = <25>; + atmel,use-dma-rx; + atmel,use-dma-tx; + status = "disabled"; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..db6a45202f26b44c6911c359902ad5e0504cbc25 --- /dev/null +++ b/arch/arm/boot/dts/at91sam9g45.dtsi @@ -0,0 +1,106 @@ +/* + * at91sam9g45.dtsi - Device Tree Include file for AT91SAM9G45 family SoC + * applies to AT91SAM9G45, AT91SAM9M10, + * AT91SAM9G46, AT91SAM9M11 SoC + * + * Copyright (C) 2011 Atmel, + * 2011 Nicolas Ferre + * + * Licensed under GPLv2 or later. + */ + +/include/ "skeleton.dtsi" + +/ { + model = "Atmel AT91SAM9G45 family SoC"; + compatible = "atmel,at91sam9g45"; + interrupt-parent = <&aic>; + + aliases { + serial0 = &dbgu; + serial1 = &usart0; + serial2 = &usart1; + serial3 = &usart2; + serial4 = &usart3; + }; + cpus { + cpu@0 { + compatible = "arm,arm926ejs"; + }; + }; + + memory@70000000 { + reg = <0x70000000 0x10000000>; + }; + + ahb { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + apb { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + aic: interrupt-controller@fffff000 { + #interrupt-cells = <1>; + compatible = "atmel,at91rm9200-aic"; + interrupt-controller; + interrupt-parent; + reg = <0xfffff000 0x200>; + }; + + dma: dma-controller@ffffec00 { + compatible = "atmel,at91sam9g45-dma"; + reg = <0xffffec00 0x200>; + interrupts = <21>; + }; + + dbgu: serial@ffffee00 { + compatible = "atmel,at91sam9260-usart"; + reg = <0xffffee00 0x200>; + interrupts = <1>; + status = "disabled"; + }; + + usart0: serial@fff8c000 { + compatible = "atmel,at91sam9260-usart"; + reg = <0xfff8c000 0x200>; + interrupts = <7>; + atmel,use-dma-rx; + atmel,use-dma-tx; + status = "disabled"; + }; + + usart1: serial@fff90000 { + compatible = "atmel,at91sam9260-usart"; + reg = <0xfff90000 0x200>; + interrupts = <8>; + atmel,use-dma-rx; + atmel,use-dma-tx; + status = "disabled"; + }; + + usart2: serial@fff94000 { + compatible = "atmel,at91sam9260-usart"; + reg = <0xfff94000 0x200>; + interrupts = <9>; + atmel,use-dma-rx; + atmel,use-dma-tx; + status = "disabled"; + }; + + usart3: serial@fff98000 { + compatible = "atmel,at91sam9260-usart"; + reg = <0xfff98000 0x200>; + interrupts = <10>; + atmel,use-dma-rx; + atmel,use-dma-tx; + status = "disabled"; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/at91sam9m10g45ek.dts b/arch/arm/boot/dts/at91sam9m10g45ek.dts new file mode 100644 index 0000000000000000000000000000000000000000..85b34f59cd82eaf0fe55d0bc5d47b19c0144783e --- /dev/null +++ b/arch/arm/boot/dts/at91sam9m10g45ek.dts @@ -0,0 +1,35 @@ +/* + * at91sam9m10g45ek.dts - Device Tree file for AT91SAM9M10G45-EK board + * + * Copyright (C) 2011 Atmel, + * 2011 Nicolas Ferre + * + * Licensed under GPLv2 or later. + */ +/dts-v1/; +/include/ "at91sam9g45.dtsi" + +/ { + model = "Atmel AT91SAM9M10G45-EK"; + compatible = "atmel,at91sam9m10g45ek", "atmel,at91sam9g45", "atmel,at91sam9"; + + chosen { + bootargs = "mem=64M console=ttyS0,115200 mtdparts=atmel_nand:4M(bootstrap/uboot/kernel)ro,60M(rootfs),-(data) root=/dev/mtdblock1 rw rootfstype=jffs2"; + }; + + memory@70000000 { + reg = <0x70000000 0x4000000>; + }; + + ahb { + apb { + dbgu: serial@ffffee00 { + status = "okay"; + }; + + usart1: serial@fff90000 { + status = "okay"; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/highbank.dts b/arch/arm/boot/dts/highbank.dts new file mode 100644 index 0000000000000000000000000000000000000000..aeb1a7578fad49e70e767358d57e602220c6c7e6 --- /dev/null +++ b/arch/arm/boot/dts/highbank.dts @@ -0,0 +1,198 @@ +/* + * Copyright 2011 Calxeda, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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, see . + */ + +/dts-v1/; + +/* First 4KB has pen for secondary cores. */ +/memreserve/ 0x00000000 0x0001000; + +/ { + model = "Calxeda Highbank"; + compatible = "calxeda,highbank"; + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + compatible = "arm,cortex-a9"; + reg = <0>; + next-level-cache = <&L2>; + }; + + cpu@1 { + compatible = "arm,cortex-a9"; + reg = <1>; + next-level-cache = <&L2>; + }; + + cpu@2 { + compatible = "arm,cortex-a9"; + reg = <2>; + next-level-cache = <&L2>; + }; + + cpu@3 { + compatible = "arm,cortex-a9"; + reg = <3>; + next-level-cache = <&L2>; + }; + }; + + memory { + name = "memory"; + device_type = "memory"; + reg = <0x00000000 0xff900000>; + }; + + chosen { + bootargs = "console=ttyAMA0"; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + interrupt-parent = <&intc>; + ranges; + + timer@fff10600 { + compatible = "arm,smp-twd"; + reg = <0xfff10600 0x20>; + interrupts = <1 13 0xf04>; + }; + + watchdog@fff10620 { + compatible = "arm,cortex-a9-wdt"; + reg = <0xfff10620 0x20>; + interrupts = <1 14 0xf04>; + }; + + intc: interrupt-controller@fff11000 { + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #size-cells = <0>; + #address-cells = <1>; + interrupt-controller; + interrupt-parent; + reg = <0xfff11000 0x1000>, + <0xfff10100 0x100>; + }; + + L2: l2-cache { + compatible = "arm,pl310-cache"; + reg = <0xfff12000 0x1000>; + interrupts = <0 70 4>; + cache-unified; + cache-level = <2>; + }; + + pmu { + compatible = "arm,cortex-a9-pmu"; + interrupts = <0 76 4 0 75 4 0 74 4 0 73 4>; + }; + + sata@ffe08000 { + compatible = "calxeda,hb-ahci"; + reg = <0xffe08000 0x10000>; + interrupts = <0 83 4>; + }; + + sdhci@ffe0e000 { + compatible = "calxeda,hb-sdhci"; + reg = <0xffe0e000 0x1000>; + interrupts = <0 90 4>; + }; + + ipc@fff20000 { + compatible = "arm,pl320", "arm,primecell"; + reg = <0xfff20000 0x1000>; + interrupts = <0 7 4>; + }; + + gpioe: gpio@fff30000 { + #gpio-cells = <2>; + compatible = "arm,pl061", "arm,primecell"; + gpio-controller; + reg = <0xfff30000 0x1000>; + interrupts = <0 14 4>; + }; + + gpiof: gpio@fff31000 { + #gpio-cells = <2>; + compatible = "arm,pl061", "arm,primecell"; + gpio-controller; + reg = <0xfff31000 0x1000>; + interrupts = <0 15 4>; + }; + + gpiog: gpio@fff32000 { + #gpio-cells = <2>; + compatible = "arm,pl061", "arm,primecell"; + gpio-controller; + reg = <0xfff32000 0x1000>; + interrupts = <0 16 4>; + }; + + gpioh: gpio@fff33000 { + #gpio-cells = <2>; + compatible = "arm,pl061", "arm,primecell"; + gpio-controller; + reg = <0xfff33000 0x1000>; + interrupts = <0 17 4>; + }; + + timer { + compatible = "arm,sp804", "arm,primecell"; + reg = <0xfff34000 0x1000>; + interrupts = <0 18 4>; + }; + + rtc@fff35000 { + compatible = "arm,pl031", "arm,primecell"; + reg = <0xfff35000 0x1000>; + interrupts = <0 19 4>; + }; + + serial@fff36000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0xfff36000 0x1000>; + interrupts = <0 20 4>; + }; + + smic@fff3a000 { + compatible = "ipmi-smic"; + device_type = "ipmi"; + reg = <0xfff3a000 0x1000>; + interrupts = <0 24 4>; + reg-size = <4>; + reg-spacing = <4>; + }; + + sregs@fff3c000 { + compatible = "calxeda,hb-sregs"; + reg = <0xfff3c000 0x1000>; + }; + + dma@fff3d000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0xfff3d000 0x1000>; + interrupts = <0 92 4>; + }; + }; +}; diff --git a/arch/arm/boot/dts/imx51-babbage.dts b/arch/arm/boot/dts/imx51-babbage.dts new file mode 100644 index 0000000000000000000000000000000000000000..f8766af11215136594cdb31fff7c1cfec968c67b --- /dev/null +++ b/arch/arm/boot/dts/imx51-babbage.dts @@ -0,0 +1,135 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. + * Copyright 2011 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/dts-v1/; +/include/ "imx51.dtsi" + +/ { + model = "Freescale i.MX51 Babbage Board"; + compatible = "fsl,imx51-babbage", "fsl,imx51"; + + chosen { + bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait"; + }; + + memory { + reg = <0x90000000 0x20000000>; + }; + + soc { + aips@70000000 { /* aips-1 */ + spba@70000000 { + esdhc@70004000 { /* ESDHC1 */ + fsl,cd-internal; + fsl,wp-internal; + status = "okay"; + }; + + esdhc@70008000 { /* ESDHC2 */ + cd-gpios = <&gpio0 6 0>; /* GPIO1_6 */ + wp-gpios = <&gpio0 5 0>; /* GPIO1_5 */ + status = "okay"; + }; + + uart2: uart@7000c000 { /* UART3 */ + fsl,uart-has-rtscts; + status = "okay"; + }; + + ecspi@70010000 { /* ECSPI1 */ + fsl,spi-num-chipselects = <2>; + cs-gpios = <&gpio3 24 0>, /* GPIO4_24 */ + <&gpio3 25 0>; /* GPIO4_25 */ + status = "okay"; + + pmic: mc13892@0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,mc13892"; + spi-max-frequency = <6000000>; + reg = <0>; + mc13xxx-irq-gpios = <&gpio0 8 0>; /* GPIO1_8 */ + fsl,mc13xxx-uses-regulator; + }; + + flash: at45db321d@1 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "atmel,at45db321d", "atmel,at45", "atmel,dataflash"; + spi-max-frequency = <25000000>; + reg = <1>; + + partition@0 { + label = "U-Boot"; + reg = <0x0 0x40000>; + read-only; + }; + + partition@40000 { + label = "Kernel"; + reg = <0x40000 0x3c0000>; + }; + }; + }; + }; + + wdog@73f98000 { /* WDOG1 */ + status = "okay"; + }; + + iomuxc@73fa8000 { + compatible = "fsl,imx51-iomuxc-babbage"; + reg = <0x73fa8000 0x4000>; + }; + + uart0: uart@73fbc000 { + fsl,uart-has-rtscts; + status = "okay"; + }; + + uart1: uart@73fc0000 { + status = "okay"; + }; + }; + + aips@80000000 { /* aips-2 */ + sdma@83fb0000 { + fsl,sdma-ram-script-name = "imx/sdma/sdma-imx51.bin"; + }; + + i2c@83fc4000 { /* I2C2 */ + status = "okay"; + + codec: sgtl5000@0a { + compatible = "fsl,sgtl5000"; + reg = <0x0a>; + }; + }; + + fec@83fec000 { + phy-mode = "mii"; + status = "okay"; + }; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + + power { + label = "Power Button"; + gpios = <&gpio1 21 0>; + linux,code = <116>; /* KEY_POWER */ + gpio-key,wakeup; + }; + }; +}; diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..327ab8e3a4c8ad63473a7121f743a9aeeeca9943 --- /dev/null +++ b/arch/arm/boot/dts/imx51.dtsi @@ -0,0 +1,246 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. + * Copyright 2011 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/include/ "skeleton.dtsi" + +/ { + aliases { + serial0 = &uart0; + serial1 = &uart1; + serial2 = &uart2; + }; + + tzic: tz-interrupt-controller@e0000000 { + compatible = "fsl,imx51-tzic", "fsl,tzic"; + interrupt-controller; + #interrupt-cells = <1>; + reg = <0xe0000000 0x4000>; + }; + + clocks { + #address-cells = <1>; + #size-cells = <0>; + + ckil { + compatible = "fsl,imx-ckil", "fixed-clock"; + clock-frequency = <32768>; + }; + + ckih1 { + compatible = "fsl,imx-ckih1", "fixed-clock"; + clock-frequency = <22579200>; + }; + + ckih2 { + compatible = "fsl,imx-ckih2", "fixed-clock"; + clock-frequency = <0>; + }; + + osc { + compatible = "fsl,imx-osc", "fixed-clock"; + clock-frequency = <24000000>; + }; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + interrupt-parent = <&tzic>; + ranges; + + aips@70000000 { /* AIPS1 */ + compatible = "fsl,aips-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x70000000 0x10000000>; + ranges; + + spba@70000000 { + compatible = "fsl,spba-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x70000000 0x40000>; + ranges; + + esdhc@70004000 { /* ESDHC1 */ + compatible = "fsl,imx51-esdhc"; + reg = <0x70004000 0x4000>; + interrupts = <1>; + status = "disabled"; + }; + + esdhc@70008000 { /* ESDHC2 */ + compatible = "fsl,imx51-esdhc"; + reg = <0x70008000 0x4000>; + interrupts = <2>; + status = "disabled"; + }; + + uart2: uart@7000c000 { /* UART3 */ + compatible = "fsl,imx51-uart", "fsl,imx21-uart"; + reg = <0x7000c000 0x4000>; + interrupts = <33>; + status = "disabled"; + }; + + ecspi@70010000 { /* ECSPI1 */ + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx51-ecspi"; + reg = <0x70010000 0x4000>; + interrupts = <36>; + status = "disabled"; + }; + + esdhc@70020000 { /* ESDHC3 */ + compatible = "fsl,imx51-esdhc"; + reg = <0x70020000 0x4000>; + interrupts = <3>; + status = "disabled"; + }; + + esdhc@70024000 { /* ESDHC4 */ + compatible = "fsl,imx51-esdhc"; + reg = <0x70024000 0x4000>; + interrupts = <4>; + status = "disabled"; + }; + }; + + gpio0: gpio@73f84000 { /* GPIO1 */ + compatible = "fsl,imx51-gpio", "fsl,imx31-gpio"; + reg = <0x73f84000 0x4000>; + interrupts = <50 51>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + gpio1: gpio@73f88000 { /* GPIO2 */ + compatible = "fsl,imx51-gpio", "fsl,imx31-gpio"; + reg = <0x73f88000 0x4000>; + interrupts = <52 53>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + gpio2: gpio@73f8c000 { /* GPIO3 */ + compatible = "fsl,imx51-gpio", "fsl,imx31-gpio"; + reg = <0x73f8c000 0x4000>; + interrupts = <54 55>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + gpio3: gpio@73f90000 { /* GPIO4 */ + compatible = "fsl,imx51-gpio", "fsl,imx31-gpio"; + reg = <0x73f90000 0x4000>; + interrupts = <56 57>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + wdog@73f98000 { /* WDOG1 */ + compatible = "fsl,imx51-wdt", "fsl,imx21-wdt"; + reg = <0x73f98000 0x4000>; + interrupts = <58>; + status = "disabled"; + }; + + wdog@73f9c000 { /* WDOG2 */ + compatible = "fsl,imx51-wdt", "fsl,imx21-wdt"; + reg = <0x73f9c000 0x4000>; + interrupts = <59>; + status = "disabled"; + }; + + uart0: uart@73fbc000 { + compatible = "fsl,imx51-uart", "fsl,imx21-uart"; + reg = <0x73fbc000 0x4000>; + interrupts = <31>; + status = "disabled"; + }; + + uart1: uart@73fc0000 { + compatible = "fsl,imx51-uart", "fsl,imx21-uart"; + reg = <0x73fc0000 0x4000>; + interrupts = <32>; + status = "disabled"; + }; + }; + + aips@80000000 { /* AIPS2 */ + compatible = "fsl,aips-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x80000000 0x10000000>; + ranges; + + ecspi@83fac000 { /* ECSPI2 */ + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx51-ecspi"; + reg = <0x83fac000 0x4000>; + interrupts = <37>; + status = "disabled"; + }; + + sdma@83fb0000 { + compatible = "fsl,imx51-sdma", "fsl,imx35-sdma"; + reg = <0x83fb0000 0x4000>; + interrupts = <6>; + }; + + cspi@83fc0000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx51-cspi", "fsl,imx35-cspi"; + reg = <0x83fc0000 0x4000>; + interrupts = <38>; + status = "disabled"; + }; + + i2c@83fc4000 { /* I2C2 */ + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx51-i2c", "fsl,imx1-i2c"; + reg = <0x83fc4000 0x4000>; + interrupts = <63>; + status = "disabled"; + }; + + i2c@83fc8000 { /* I2C1 */ + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx51-i2c", "fsl,imx1-i2c"; + reg = <0x83fc8000 0x4000>; + interrupts = <62>; + status = "disabled"; + }; + + fec@83fec000 { + compatible = "fsl,imx51-fec", "fsl,imx27-fec"; + reg = <0x83fec000 0x4000>; + interrupts = <87>; + status = "disabled"; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/imx53-ard.dts b/arch/arm/boot/dts/imx53-ard.dts new file mode 100644 index 0000000000000000000000000000000000000000..2ab7f80a0a35c3c03fccf3d5a60ed69fad2f9f26 --- /dev/null +++ b/arch/arm/boot/dts/imx53-ard.dts @@ -0,0 +1,113 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. + * Copyright 2011 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/dts-v1/; +/include/ "imx53.dtsi" + +/ { + model = "Freescale i.MX53 Automotive Reference Design Board"; + compatible = "fsl,imx53-ard", "fsl,imx53"; + + chosen { + bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait"; + }; + + memory { + reg = <0x70000000 0x40000000>; + }; + + soc { + aips@50000000 { /* AIPS1 */ + spba@50000000 { + esdhc@50004000 { /* ESDHC1 */ + cd-gpios = <&gpio0 1 0>; /* GPIO1_1 */ + wp-gpios = <&gpio0 9 0>; /* GPIO1_9 */ + status = "okay"; + }; + }; + + wdog@53f98000 { /* WDOG1 */ + status = "okay"; + }; + + iomuxc@53fa8000 { + compatible = "fsl,imx53-iomuxc-ard"; + reg = <0x53fa8000 0x4000>; + }; + + uart0: uart@53fbc000 { /* UART1 */ + status = "okay"; + }; + }; + + aips@60000000 { /* AIPS2 */ + sdma@63fb0000 { + fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin"; + }; + }; + }; + + eim-cs1@f4000000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "fsl,eim-bus", "simple-bus"; + reg = <0xf4000000 0x3ff0000>; + ranges; + + lan9220@f4000000 { + compatible = "smsc,lan9220", "smsc,lan9115"; + reg = <0xf4000000 0x2000000>; + phy-mode = "mii"; + interrupt-parent = <&gpio1>; + interrupts = <31>; + reg-io-width = <4>; + smsc,irq-push-pull; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + + home { + label = "Home"; + gpios = <&gpio4 10 0>; /* GPIO5_10 */ + linux,code = <102>; /* KEY_HOME */ + gpio-key,wakeup; + }; + + back { + label = "Back"; + gpios = <&gpio4 11 0>; /* GPIO5_11 */ + linux,code = <158>; /* KEY_BACK */ + gpio-key,wakeup; + }; + + program { + label = "Program"; + gpios = <&gpio4 12 0>; /* GPIO5_12 */ + linux,code = <362>; /* KEY_PROGRAM */ + gpio-key,wakeup; + }; + + volume-up { + label = "Volume Up"; + gpios = <&gpio4 13 0>; /* GPIO5_13 */ + linux,code = <115>; /* KEY_VOLUMEUP */ + }; + + volume-down { + label = "Volume Down"; + gpios = <&gpio3 0 0>; /* GPIO4_0 */ + linux,code = <114>; /* KEY_VOLUMEDOWN */ + }; + }; +}; diff --git a/arch/arm/boot/dts/imx53-evk.dts b/arch/arm/boot/dts/imx53-evk.dts new file mode 100644 index 0000000000000000000000000000000000000000..3f3a88185ff8e6fb860f1033ff89f5f13d107989 --- /dev/null +++ b/arch/arm/boot/dts/imx53-evk.dts @@ -0,0 +1,120 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. + * Copyright 2011 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/dts-v1/; +/include/ "imx53.dtsi" + +/ { + model = "Freescale i.MX53 Evaluation Kit"; + compatible = "fsl,imx53-evk", "fsl,imx53"; + + chosen { + bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait"; + }; + + memory { + reg = <0x70000000 0x80000000>; + }; + + soc { + aips@50000000 { /* AIPS1 */ + spba@50000000 { + esdhc@50004000 { /* ESDHC1 */ + cd-gpios = <&gpio2 13 0>; /* GPIO3_13 */ + wp-gpios = <&gpio2 14 0>; /* GPIO3_14 */ + status = "okay"; + }; + + ecspi@50010000 { /* ECSPI1 */ + fsl,spi-num-chipselects = <2>; + cs-gpios = <&gpio1 30 0>, /* GPIO2_30 */ + <&gpio2 19 0>; /* GPIO3_19 */ + status = "okay"; + + flash: at45db321d@1 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "atmel,at45db321d", "atmel,at45", "atmel,dataflash"; + spi-max-frequency = <25000000>; + reg = <1>; + + partition@0 { + label = "U-Boot"; + reg = <0x0 0x40000>; + read-only; + }; + + partition@40000 { + label = "Kernel"; + reg = <0x40000 0x3c0000>; + }; + }; + }; + + esdhc@50020000 { /* ESDHC3 */ + cd-gpios = <&gpio2 11 0>; /* GPIO3_11 */ + wp-gpios = <&gpio2 12 0>; /* GPIO3_12 */ + status = "okay"; + }; + }; + + wdog@53f98000 { /* WDOG1 */ + status = "okay"; + }; + + iomuxc@53fa8000 { + compatible = "fsl,imx53-iomuxc-evk"; + reg = <0x53fa8000 0x4000>; + }; + + uart0: uart@53fbc000 { /* UART1 */ + status = "okay"; + }; + }; + + aips@60000000 { /* AIPS2 */ + sdma@63fb0000 { + fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin"; + }; + + i2c@63fc4000 { /* I2C2 */ + status = "okay"; + + pmic: mc13892@08 { + compatible = "fsl,mc13892", "fsl,mc13xxx"; + reg = <0x08>; + }; + + codec: sgtl5000@0a { + compatible = "fsl,sgtl5000"; + reg = <0x0a>; + }; + }; + + fec@63fec000 { + phy-mode = "rmii"; + phy-reset-gpios = <&gpio6 6 0>; /* GPIO7_6 */ + status = "okay"; + }; + }; + }; + + leds { + compatible = "gpio-leds"; + + green { + label = "Heartbeat"; + gpios = <&gpio6 7 0>; /* GPIO7_7 */ + linux,default-trigger = "heartbeat"; + }; + }; +}; diff --git a/arch/arm/boot/dts/imx53-qsb.dts b/arch/arm/boot/dts/imx53-qsb.dts new file mode 100644 index 0000000000000000000000000000000000000000..ae6de6d0c3f1b57ee23f52b596f3eda1c8468014 --- /dev/null +++ b/arch/arm/boot/dts/imx53-qsb.dts @@ -0,0 +1,125 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. + * Copyright 2011 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/dts-v1/; +/include/ "imx53.dtsi" + +/ { + model = "Freescale i.MX53 Quick Start Board"; + compatible = "fsl,imx53-qsb", "fsl,imx53"; + + chosen { + bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait"; + }; + + memory { + reg = <0x70000000 0x40000000>; + }; + + soc { + aips@50000000 { /* AIPS1 */ + spba@50000000 { + esdhc@50004000 { /* ESDHC1 */ + cd-gpios = <&gpio2 13 0>; /* GPIO3_13 */ + status = "okay"; + }; + + esdhc@50020000 { /* ESDHC3 */ + cd-gpios = <&gpio2 11 0>; /* GPIO3_11 */ + wp-gpios = <&gpio2 12 0>; /* GPIO3_12 */ + status = "okay"; + }; + }; + + wdog@53f98000 { /* WDOG1 */ + status = "okay"; + }; + + iomuxc@53fa8000 { + compatible = "fsl,imx53-iomuxc-qsb"; + reg = <0x53fa8000 0x4000>; + }; + + uart0: uart@53fbc000 { /* UART1 */ + status = "okay"; + }; + }; + + aips@60000000 { /* AIPS2 */ + sdma@63fb0000 { + fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin"; + }; + + i2c@63fc4000 { /* I2C2 */ + status = "okay"; + + codec: sgtl5000@0a { + compatible = "fsl,sgtl5000"; + reg = <0x0a>; + }; + }; + + i2c@63fc8000 { /* I2C1 */ + status = "okay"; + + accelerometer: mma8450@1c { + compatible = "fsl,mma8450"; + reg = <0x1c>; + }; + + pmic: dialog@48 { + compatible = "dialog,da9053", "dialog,da9052"; + reg = <0x48>; + }; + }; + + fec@63fec000 { + phy-mode = "rmii"; + phy-reset-gpios = <&gpio6 6 0>; /* GPIO7_6 */ + status = "okay"; + }; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + + power { + label = "Power Button"; + gpios = <&gpio0 8 0>; /* GPIO1_8 */ + linux,code = <116>; /* KEY_POWER */ + gpio-key,wakeup; + }; + + volume-up { + label = "Volume Up"; + gpios = <&gpio1 14 0>; /* GPIO2_14 */ + linux,code = <115>; /* KEY_VOLUMEUP */ + }; + + volume-down { + label = "Volume Down"; + gpios = <&gpio1 15 0>; /* GPIO2_15 */ + linux,code = <114>; /* KEY_VOLUMEDOWN */ + }; + }; + + leds { + compatible = "gpio-leds"; + + user { + label = "Heartbeat"; + gpios = <&gpio6 7 0>; /* GPIO7_7 */ + linux,default-trigger = "heartbeat"; + }; + }; +}; diff --git a/arch/arm/boot/dts/imx53-smd.dts b/arch/arm/boot/dts/imx53-smd.dts new file mode 100644 index 0000000000000000000000000000000000000000..b1c062eea715bc2995e329998ee40200930483fd --- /dev/null +++ b/arch/arm/boot/dts/imx53-smd.dts @@ -0,0 +1,169 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. + * Copyright 2011 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/dts-v1/; +/include/ "imx53.dtsi" + +/ { + model = "Freescale i.MX53 Smart Mobile Reference Design Board"; + compatible = "fsl,imx53-smd", "fsl,imx53"; + + chosen { + bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait"; + }; + + memory { + reg = <0x70000000 0x40000000>; + }; + + soc { + aips@50000000 { /* AIPS1 */ + spba@50000000 { + esdhc@50004000 { /* ESDHC1 */ + cd-gpios = <&gpio2 13 0>; /* GPIO3_13 */ + wp-gpios = <&gpio3 11 0>; /* GPIO4_11 */ + status = "okay"; + }; + + esdhc@50008000 { /* ESDHC2 */ + fsl,card-wired; + status = "okay"; + }; + + uart2: uart@5000c000 { /* UART3 */ + fsl,uart-has-rtscts; + status = "okay"; + }; + + ecspi@50010000 { /* ECSPI1 */ + fsl,spi-num-chipselects = <2>; + cs-gpios = <&gpio1 30 0>, /* GPIO2_30 */ + <&gpio2 19 0>; /* GPIO3_19 */ + status = "okay"; + + zigbee: mc1323@0 { + compatible = "fsl,mc1323"; + spi-max-frequency = <8000000>; + reg = <0>; + }; + + flash: m25p32@1 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,m25p32", "st,m25p"; + spi-max-frequency = <20000000>; + reg = <1>; + + partition@0 { + label = "U-Boot"; + reg = <0x0 0x40000>; + read-only; + }; + + partition@40000 { + label = "Kernel"; + reg = <0x40000 0x3c0000>; + }; + }; + }; + + esdhc@50020000 { /* ESDHC3 */ + fsl,card-wired; + status = "okay"; + }; + }; + + wdog@53f98000 { /* WDOG1 */ + status = "okay"; + }; + + iomuxc@53fa8000 { + compatible = "fsl,imx53-iomuxc-smd"; + reg = <0x53fa8000 0x4000>; + }; + + uart0: uart@53fbc000 { /* UART1 */ + status = "okay"; + }; + + uart1: uart@53fc0000 { /* UART2 */ + status = "okay"; + }; + }; + + aips@60000000 { /* AIPS2 */ + sdma@63fb0000 { + fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin"; + }; + + i2c@63fc4000 { /* I2C2 */ + status = "okay"; + + codec: sgtl5000@0a { + compatible = "fsl,sgtl5000"; + reg = <0x0a>; + }; + + magnetometer: mag3110@0e { + compatible = "fsl,mag3110"; + reg = <0x0e>; + }; + + touchkey: mpr121@5a { + compatible = "fsl,mpr121"; + reg = <0x5a>; + }; + }; + + i2c@63fc8000 { /* I2C1 */ + status = "okay"; + + accelerometer: mma8450@1c { + compatible = "fsl,mma8450"; + reg = <0x1c>; + }; + + camera: ov5642@3c { + compatible = "ovti,ov5642"; + reg = <0x3c>; + }; + + pmic: dialog@48 { + compatible = "dialog,da9053", "dialog,da9052"; + reg = <0x48>; + }; + }; + + fec@63fec000 { + phy-mode = "rmii"; + phy-reset-gpios = <&gpio6 6 0>; /* GPIO7_6 */ + status = "okay"; + }; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + + volume-up { + label = "Volume Up"; + gpios = <&gpio1 14 0>; /* GPIO2_14 */ + linux,code = <115>; /* KEY_VOLUMEUP */ + }; + + volume-down { + label = "Volume Down"; + gpios = <&gpio1 15 0>; /* GPIO2_15 */ + linux,code = <114>; /* KEY_VOLUMEDOWN */ + }; + }; +}; diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..099cd84ee372cb281c5b4f1c4753c4ca730fc264 --- /dev/null +++ b/arch/arm/boot/dts/imx53.dtsi @@ -0,0 +1,301 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. + * Copyright 2011 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/include/ "skeleton.dtsi" + +/ { + aliases { + serial0 = &uart0; + serial1 = &uart1; + serial2 = &uart2; + serial3 = &uart3; + serial4 = &uart4; + }; + + tzic: tz-interrupt-controller@0fffc000 { + compatible = "fsl,imx53-tzic", "fsl,tzic"; + interrupt-controller; + #interrupt-cells = <1>; + reg = <0x0fffc000 0x4000>; + }; + + clocks { + #address-cells = <1>; + #size-cells = <0>; + + ckil { + compatible = "fsl,imx-ckil", "fixed-clock"; + clock-frequency = <32768>; + }; + + ckih1 { + compatible = "fsl,imx-ckih1", "fixed-clock"; + clock-frequency = <22579200>; + }; + + ckih2 { + compatible = "fsl,imx-ckih2", "fixed-clock"; + clock-frequency = <0>; + }; + + osc { + compatible = "fsl,imx-osc", "fixed-clock"; + clock-frequency = <24000000>; + }; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + interrupt-parent = <&tzic>; + ranges; + + aips@50000000 { /* AIPS1 */ + compatible = "fsl,aips-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x50000000 0x10000000>; + ranges; + + spba@50000000 { + compatible = "fsl,spba-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x50000000 0x40000>; + ranges; + + esdhc@50004000 { /* ESDHC1 */ + compatible = "fsl,imx53-esdhc"; + reg = <0x50004000 0x4000>; + interrupts = <1>; + status = "disabled"; + }; + + esdhc@50008000 { /* ESDHC2 */ + compatible = "fsl,imx53-esdhc"; + reg = <0x50008000 0x4000>; + interrupts = <2>; + status = "disabled"; + }; + + uart2: uart@5000c000 { /* UART3 */ + compatible = "fsl,imx53-uart", "fsl,imx21-uart"; + reg = <0x5000c000 0x4000>; + interrupts = <33>; + status = "disabled"; + }; + + ecspi@50010000 { /* ECSPI1 */ + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi"; + reg = <0x50010000 0x4000>; + interrupts = <36>; + status = "disabled"; + }; + + esdhc@50020000 { /* ESDHC3 */ + compatible = "fsl,imx53-esdhc"; + reg = <0x50020000 0x4000>; + interrupts = <3>; + status = "disabled"; + }; + + esdhc@50024000 { /* ESDHC4 */ + compatible = "fsl,imx53-esdhc"; + reg = <0x50024000 0x4000>; + interrupts = <4>; + status = "disabled"; + }; + }; + + gpio0: gpio@53f84000 { /* GPIO1 */ + compatible = "fsl,imx53-gpio", "fsl,imx31-gpio"; + reg = <0x53f84000 0x4000>; + interrupts = <50 51>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + gpio1: gpio@53f88000 { /* GPIO2 */ + compatible = "fsl,imx53-gpio", "fsl,imx31-gpio"; + reg = <0x53f88000 0x4000>; + interrupts = <52 53>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + gpio2: gpio@53f8c000 { /* GPIO3 */ + compatible = "fsl,imx53-gpio", "fsl,imx31-gpio"; + reg = <0x53f8c000 0x4000>; + interrupts = <54 55>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + gpio3: gpio@53f90000 { /* GPIO4 */ + compatible = "fsl,imx53-gpio", "fsl,imx31-gpio"; + reg = <0x53f90000 0x4000>; + interrupts = <56 57>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + wdog@53f98000 { /* WDOG1 */ + compatible = "fsl,imx53-wdt", "fsl,imx21-wdt"; + reg = <0x53f98000 0x4000>; + interrupts = <58>; + status = "disabled"; + }; + + wdog@53f9c000 { /* WDOG2 */ + compatible = "fsl,imx53-wdt", "fsl,imx21-wdt"; + reg = <0x53f9c000 0x4000>; + interrupts = <59>; + status = "disabled"; + }; + + uart0: uart@53fbc000 { /* UART1 */ + compatible = "fsl,imx53-uart", "fsl,imx21-uart"; + reg = <0x53fbc000 0x4000>; + interrupts = <31>; + status = "disabled"; + }; + + uart1: uart@53fc0000 { /* UART2 */ + compatible = "fsl,imx53-uart", "fsl,imx21-uart"; + reg = <0x53fc0000 0x4000>; + interrupts = <32>; + status = "disabled"; + }; + + gpio4: gpio@53fdc000 { /* GPIO5 */ + compatible = "fsl,imx53-gpio", "fsl,imx31-gpio"; + reg = <0x53fdc000 0x4000>; + interrupts = <103 104>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + gpio5: gpio@53fe0000 { /* GPIO6 */ + compatible = "fsl,imx53-gpio", "fsl,imx31-gpio"; + reg = <0x53fe0000 0x4000>; + interrupts = <105 106>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + gpio6: gpio@53fe4000 { /* GPIO7 */ + compatible = "fsl,imx53-gpio", "fsl,imx31-gpio"; + reg = <0x53fe4000 0x4000>; + interrupts = <107 108>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + i2c@53fec000 { /* I2C3 */ + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx53-i2c", "fsl,imx1-i2c"; + reg = <0x53fec000 0x4000>; + interrupts = <64>; + status = "disabled"; + }; + + uart3: uart@53ff0000 { /* UART4 */ + compatible = "fsl,imx53-uart", "fsl,imx21-uart"; + reg = <0x53ff0000 0x4000>; + interrupts = <13>; + status = "disabled"; + }; + }; + + aips@60000000 { /* AIPS2 */ + compatible = "fsl,aips-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x60000000 0x10000000>; + ranges; + + uart4: uart@63f90000 { /* UART5 */ + compatible = "fsl,imx53-uart", "fsl,imx21-uart"; + reg = <0x63f90000 0x4000>; + interrupts = <86>; + status = "disabled"; + }; + + ecspi@63fac000 { /* ECSPI2 */ + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi"; + reg = <0x63fac000 0x4000>; + interrupts = <37>; + status = "disabled"; + }; + + sdma@63fb0000 { + compatible = "fsl,imx53-sdma", "fsl,imx35-sdma"; + reg = <0x63fb0000 0x4000>; + interrupts = <6>; + }; + + cspi@63fc0000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx53-cspi", "fsl,imx35-cspi"; + reg = <0x63fc0000 0x4000>; + interrupts = <38>; + status = "disabled"; + }; + + i2c@63fc4000 { /* I2C2 */ + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx53-i2c", "fsl,imx1-i2c"; + reg = <0x63fc4000 0x4000>; + interrupts = <63>; + status = "disabled"; + }; + + i2c@63fc8000 { /* I2C1 */ + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx53-i2c", "fsl,imx1-i2c"; + reg = <0x63fc8000 0x4000>; + interrupts = <62>; + status = "disabled"; + }; + + fec@63fec000 { + compatible = "fsl,imx53-fec", "fsl,imx25-fec"; + reg = <0x63fec000 0x4000>; + interrupts = <87>; + status = "disabled"; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/imx6q-sabreauto.dts b/arch/arm/boot/dts/imx6q-sabreauto.dts new file mode 100644 index 0000000000000000000000000000000000000000..072974e443f22b20eb7127511f2c176b1abc7720 --- /dev/null +++ b/arch/arm/boot/dts/imx6q-sabreauto.dts @@ -0,0 +1,62 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. + * Copyright 2011 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/dts-v1/; +/include/ "imx6q.dtsi" + +/ { + model = "Freescale i.MX6 Quad SABRE Automotive Board"; + compatible = "fsl,imx6q-sabreauto", "fsl,imx6q"; + + chosen { + bootargs = "console=ttymxc0,115200 root=/dev/mmcblk3p3 rootwait"; + }; + + memory { + reg = <0x10000000 0x80000000>; + }; + + soc { + aips-bus@02100000 { /* AIPS2 */ + enet@02188000 { + phy-mode = "rgmii"; + local-mac-address = [00 04 9F 01 1B 61]; + status = "okay"; + }; + + usdhc@02198000 { /* uSDHC3 */ + cd-gpios = <&gpio5 11 0>; /* GPIO6_11 */ + wp-gpios = <&gpio5 14 0>; /* GPIO6_14 */ + status = "okay"; + }; + + usdhc@0219c000 { /* uSDHC4 */ + fsl,card-wired; + status = "okay"; + }; + + uart3: uart@021f0000 { /* UART4 */ + status = "okay"; + }; + }; + }; + + leds { + compatible = "gpio-leds"; + + debug-led { + label = "Heartbeat"; + gpios = <&gpio2 25 0>; /* GPIO3_25 */ + linux,default-trigger = "heartbeat"; + }; + }; +}; diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..7dda599558cc0b54b4ff2aa6a20756cd0d623bbc --- /dev/null +++ b/arch/arm/boot/dts/imx6q.dtsi @@ -0,0 +1,575 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. + * Copyright 2011 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/include/ "skeleton.dtsi" + +/ { + aliases { + serial0 = &uart0; + serial1 = &uart1; + serial2 = &uart2; + serial3 = &uart3; + serial4 = &uart4; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + compatible = "arm,cortex-a9"; + reg = <0>; + next-level-cache = <&L2>; + }; + + cpu@1 { + compatible = "arm,cortex-a9"; + reg = <1>; + next-level-cache = <&L2>; + }; + + cpu@2 { + compatible = "arm,cortex-a9"; + reg = <2>; + next-level-cache = <&L2>; + }; + + cpu@3 { + compatible = "arm,cortex-a9"; + reg = <3>; + next-level-cache = <&L2>; + }; + }; + + intc: interrupt-controller@00a01000 { + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <1>; + #size-cells = <1>; + interrupt-controller; + reg = <0x00a01000 0x1000>, + <0x00a00100 0x100>; + }; + + clocks { + #address-cells = <1>; + #size-cells = <0>; + + ckil { + compatible = "fsl,imx-ckil", "fixed-clock"; + clock-frequency = <32768>; + }; + + ckih1 { + compatible = "fsl,imx-ckih1", "fixed-clock"; + clock-frequency = <0>; + }; + + osc { + compatible = "fsl,imx-osc", "fixed-clock"; + clock-frequency = <24000000>; + }; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + interrupt-parent = <&intc>; + ranges; + + timer@00a00600 { + compatible = "arm,smp-twd"; + reg = <0x00a00600 0x100>; + interrupts = <1 13 0xf4>; + }; + + L2: l2-cache@00a02000 { + compatible = "arm,pl310-cache"; + reg = <0x00a02000 0x1000>; + interrupts = <0 92 0x04>; + cache-unified; + cache-level = <2>; + }; + + aips-bus@02000000 { /* AIPS1 */ + compatible = "fsl,aips-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x02000000 0x100000>; + ranges; + + spba-bus@02000000 { + compatible = "fsl,spba-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x02000000 0x40000>; + ranges; + + spdif@02004000 { + reg = <0x02004000 0x4000>; + interrupts = <0 52 0x04>; + }; + + ecspi@02008000 { /* eCSPI1 */ + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi"; + reg = <0x02008000 0x4000>; + interrupts = <0 31 0x04>; + status = "disabled"; + }; + + ecspi@0200c000 { /* eCSPI2 */ + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi"; + reg = <0x0200c000 0x4000>; + interrupts = <0 32 0x04>; + status = "disabled"; + }; + + ecspi@02010000 { /* eCSPI3 */ + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi"; + reg = <0x02010000 0x4000>; + interrupts = <0 33 0x04>; + status = "disabled"; + }; + + ecspi@02014000 { /* eCSPI4 */ + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi"; + reg = <0x02014000 0x4000>; + interrupts = <0 34 0x04>; + status = "disabled"; + }; + + ecspi@02018000 { /* eCSPI5 */ + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi"; + reg = <0x02018000 0x4000>; + interrupts = <0 35 0x04>; + status = "disabled"; + }; + + uart0: uart@02020000 { /* UART1 */ + compatible = "fsl,imx6q-uart", "fsl,imx21-uart"; + reg = <0x02020000 0x4000>; + interrupts = <0 26 0x04>; + status = "disabled"; + }; + + esai@02024000 { + reg = <0x02024000 0x4000>; + interrupts = <0 51 0x04>; + }; + + ssi@02028000 { /* SSI1 */ + reg = <0x02028000 0x4000>; + interrupts = <0 46 0x04>; + }; + + ssi@0202c000 { /* SSI2 */ + reg = <0x0202c000 0x4000>; + interrupts = <0 47 0x04>; + }; + + ssi@02030000 { /* SSI3 */ + reg = <0x02030000 0x4000>; + interrupts = <0 48 0x04>; + }; + + asrc@02034000 { + reg = <0x02034000 0x4000>; + interrupts = <0 50 0x04>; + }; + + spba@0203c000 { + reg = <0x0203c000 0x4000>; + }; + }; + + vpu@02040000 { + reg = <0x02040000 0x3c000>; + interrupts = <0 3 0x04 0 12 0x04>; + }; + + aipstz@0207c000 { /* AIPSTZ1 */ + reg = <0x0207c000 0x4000>; + }; + + pwm@02080000 { /* PWM1 */ + reg = <0x02080000 0x4000>; + interrupts = <0 83 0x04>; + }; + + pwm@02084000 { /* PWM2 */ + reg = <0x02084000 0x4000>; + interrupts = <0 84 0x04>; + }; + + pwm@02088000 { /* PWM3 */ + reg = <0x02088000 0x4000>; + interrupts = <0 85 0x04>; + }; + + pwm@0208c000 { /* PWM4 */ + reg = <0x0208c000 0x4000>; + interrupts = <0 86 0x04>; + }; + + flexcan@02090000 { /* CAN1 */ + reg = <0x02090000 0x4000>; + interrupts = <0 110 0x04>; + }; + + flexcan@02094000 { /* CAN2 */ + reg = <0x02094000 0x4000>; + interrupts = <0 111 0x04>; + }; + + gpt@02098000 { + compatible = "fsl,imx6q-gpt"; + reg = <0x02098000 0x4000>; + interrupts = <0 55 0x04>; + }; + + gpio0: gpio@0209c000 { /* GPIO1 */ + compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio"; + reg = <0x0209c000 0x4000>; + interrupts = <0 66 0x04 0 67 0x04>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + gpio1: gpio@020a0000 { /* GPIO2 */ + compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio"; + reg = <0x020a0000 0x4000>; + interrupts = <0 68 0x04 0 69 0x04>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + gpio2: gpio@020a4000 { /* GPIO3 */ + compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio"; + reg = <0x020a4000 0x4000>; + interrupts = <0 70 0x04 0 71 0x04>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + gpio3: gpio@020a8000 { /* GPIO4 */ + compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio"; + reg = <0x020a8000 0x4000>; + interrupts = <0 72 0x04 0 73 0x04>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + gpio4: gpio@020ac000 { /* GPIO5 */ + compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio"; + reg = <0x020ac000 0x4000>; + interrupts = <0 74 0x04 0 75 0x04>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + gpio5: gpio@020b0000 { /* GPIO6 */ + compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio"; + reg = <0x020b0000 0x4000>; + interrupts = <0 76 0x04 0 77 0x04>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + gpio6: gpio@020b4000 { /* GPIO7 */ + compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio"; + reg = <0x020b4000 0x4000>; + interrupts = <0 78 0x04 0 79 0x04>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + kpp@020b8000 { + reg = <0x020b8000 0x4000>; + interrupts = <0 82 0x04>; + }; + + wdog@020bc000 { /* WDOG1 */ + compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt"; + reg = <0x020bc000 0x4000>; + interrupts = <0 80 0x04>; + status = "disabled"; + }; + + wdog@020c0000 { /* WDOG2 */ + compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt"; + reg = <0x020c0000 0x4000>; + interrupts = <0 81 0x04>; + status = "disabled"; + }; + + ccm@020c4000 { + compatible = "fsl,imx6q-ccm"; + reg = <0x020c4000 0x4000>; + interrupts = <0 87 0x04 0 88 0x04>; + }; + + anatop@020c8000 { + compatible = "fsl,imx6q-anatop"; + reg = <0x020c8000 0x1000>; + interrupts = <0 49 0x04 0 54 0x04 0 127 0x04>; + }; + + usbphy@020c9000 { /* USBPHY1 */ + reg = <0x020c9000 0x1000>; + interrupts = <0 44 0x04>; + }; + + usbphy@020ca000 { /* USBPHY2 */ + reg = <0x020ca000 0x1000>; + interrupts = <0 45 0x04>; + }; + + snvs@020cc000 { + reg = <0x020cc000 0x4000>; + interrupts = <0 19 0x04 0 20 0x04>; + }; + + epit@020d0000 { /* EPIT1 */ + reg = <0x020d0000 0x4000>; + interrupts = <0 56 0x04>; + }; + + epit@020d4000 { /* EPIT2 */ + reg = <0x020d4000 0x4000>; + interrupts = <0 57 0x04>; + }; + + src@020d8000 { + compatible = "fsl,imx6q-src"; + reg = <0x020d8000 0x4000>; + interrupts = <0 91 0x04 0 96 0x04>; + }; + + gpc@020dc000 { + compatible = "fsl,imx6q-gpc"; + reg = <0x020dc000 0x4000>; + interrupts = <0 89 0x04 0 90 0x04>; + }; + + iomuxc@020e0000 { + reg = <0x020e0000 0x4000>; + }; + + dcic@020e4000 { /* DCIC1 */ + reg = <0x020e4000 0x4000>; + interrupts = <0 124 0x04>; + }; + + dcic@020e8000 { /* DCIC2 */ + reg = <0x020e8000 0x4000>; + interrupts = <0 125 0x04>; + }; + + sdma@020ec000 { + compatible = "fsl,imx6q-sdma", "fsl,imx35-sdma"; + reg = <0x020ec000 0x4000>; + interrupts = <0 2 0x04>; + }; + }; + + aips-bus@02100000 { /* AIPS2 */ + compatible = "fsl,aips-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x02100000 0x100000>; + ranges; + + caam@02100000 { + reg = <0x02100000 0x40000>; + interrupts = <0 105 0x04 0 106 0x04>; + }; + + aipstz@0217c000 { /* AIPSTZ2 */ + reg = <0x0217c000 0x4000>; + }; + + enet@02188000 { + compatible = "fsl,imx6q-fec"; + reg = <0x02188000 0x4000>; + interrupts = <0 118 0x04 0 119 0x04>; + status = "disabled"; + }; + + mlb@0218c000 { + reg = <0x0218c000 0x4000>; + interrupts = <0 53 0x04 0 117 0x04 0 126 0x04>; + }; + + usdhc@02190000 { /* uSDHC1 */ + compatible = "fsl,imx6q-usdhc"; + reg = <0x02190000 0x4000>; + interrupts = <0 22 0x04>; + status = "disabled"; + }; + + usdhc@02194000 { /* uSDHC2 */ + compatible = "fsl,imx6q-usdhc"; + reg = <0x02194000 0x4000>; + interrupts = <0 23 0x04>; + status = "disabled"; + }; + + usdhc@02198000 { /* uSDHC3 */ + compatible = "fsl,imx6q-usdhc"; + reg = <0x02198000 0x4000>; + interrupts = <0 24 0x04>; + status = "disabled"; + }; + + usdhc@0219c000 { /* uSDHC4 */ + compatible = "fsl,imx6q-usdhc"; + reg = <0x0219c000 0x4000>; + interrupts = <0 25 0x04>; + status = "disabled"; + }; + + i2c@021a0000 { /* I2C1 */ + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c"; + reg = <0x021a0000 0x4000>; + interrupts = <0 36 0x04>; + status = "disabled"; + }; + + i2c@021a4000 { /* I2C2 */ + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c"; + reg = <0x021a4000 0x4000>; + interrupts = <0 37 0x04>; + status = "disabled"; + }; + + i2c@021a8000 { /* I2C3 */ + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c"; + reg = <0x021a8000 0x4000>; + interrupts = <0 38 0x04>; + status = "disabled"; + }; + + romcp@021ac000 { + reg = <0x021ac000 0x4000>; + }; + + mmdc@021b0000 { /* MMDC0 */ + compatible = "fsl,imx6q-mmdc"; + reg = <0x021b0000 0x4000>; + }; + + mmdc@021b4000 { /* MMDC1 */ + reg = <0x021b4000 0x4000>; + }; + + weim@021b8000 { + reg = <0x021b8000 0x4000>; + interrupts = <0 14 0x04>; + }; + + ocotp@021bc000 { + reg = <0x021bc000 0x4000>; + }; + + ocotp@021c0000 { + reg = <0x021c0000 0x4000>; + interrupts = <0 21 0x04>; + }; + + tzasc@021d0000 { /* TZASC1 */ + reg = <0x021d0000 0x4000>; + interrupts = <0 108 0x04>; + }; + + tzasc@021d4000 { /* TZASC2 */ + reg = <0x021d4000 0x4000>; + interrupts = <0 109 0x04>; + }; + + audmux@021d8000 { + reg = <0x021d8000 0x4000>; + }; + + mipi@021dc000 { /* MIPI-CSI */ + reg = <0x021dc000 0x4000>; + }; + + mipi@021e0000 { /* MIPI-DSI */ + reg = <0x021e0000 0x4000>; + }; + + vdoa@021e4000 { + reg = <0x021e4000 0x4000>; + interrupts = <0 18 0x04>; + }; + + uart1: uart@021e8000 { /* UART2 */ + compatible = "fsl,imx6q-uart", "fsl,imx21-uart"; + reg = <0x021e8000 0x4000>; + interrupts = <0 27 0x04>; + status = "disabled"; + }; + + uart2: uart@021ec000 { /* UART3 */ + compatible = "fsl,imx6q-uart", "fsl,imx21-uart"; + reg = <0x021ec000 0x4000>; + interrupts = <0 28 0x04>; + status = "disabled"; + }; + + uart3: uart@021f0000 { /* UART4 */ + compatible = "fsl,imx6q-uart", "fsl,imx21-uart"; + reg = <0x021f0000 0x4000>; + interrupts = <0 29 0x04>; + status = "disabled"; + }; + + uart4: uart@021f4000 { /* UART5 */ + compatible = "fsl,imx6q-uart", "fsl,imx21-uart"; + reg = <0x021f4000 0x4000>; + interrupts = <0 30 0x04>; + status = "disabled"; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/msm8660-surf.dts b/arch/arm/boot/dts/msm8660-surf.dts new file mode 100644 index 0000000000000000000000000000000000000000..15ded0deaa79aec744760a00b8f80e9f81fe4228 --- /dev/null +++ b/arch/arm/boot/dts/msm8660-surf.dts @@ -0,0 +1,24 @@ +/dts-v1/; + +/include/ "skeleton.dtsi" + +/ { + model = "Qualcomm MSM8660 SURF"; + compatible = "qcom,msm8660-surf", "qcom,msm8660"; + interrupt-parent = <&intc>; + + intc: interrupt-controller@02080000 { + compatible = "qcom,msm-8660-qgic"; + interrupt-controller; + #interrupt-cells = <1>; + reg = < 0x02080000 0x1000 >, + < 0x02081000 0x1000 >; + }; + + serial@19c400000 { + compatible = "qcom,msm-hsuart", "qcom,msm-uart"; + reg = <0x19c40000 0x1000>, + <0x19c00000 0x1000>; + interrupts = <195>; + }; +}; diff --git a/arch/arm/boot/dts/omap3-beagle.dts b/arch/arm/boot/dts/omap3-beagle.dts new file mode 100644 index 0000000000000000000000000000000000000000..9486be62bcddcd4674c9f0daa7e9f0f7b86f8147 --- /dev/null +++ b/arch/arm/boot/dts/omap3-beagle.dts @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ +/dts-v1/; + +/include/ "omap3.dtsi" + +/ { + model = "TI OMAP3 BeagleBoard"; + compatible = "ti,omap3-beagle", "ti,omap3"; + + /* + * Since the initial device tree board file does not create any + * devices (MMC, network...), the only way to boot is to provide a + * ramdisk. + */ + chosen { + bootargs = "root=/dev/ram0 rw console=ttyO2,115200n8 initrd=0x81600000,20M ramdisk_size=20480 no_console_suspend debug earlyprintk"; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x20000000>; /* 512 MB */ + }; +}; diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..d202bb5ec7efe3912cc9ea285bde04479741e4ef --- /dev/null +++ b/arch/arm/boot/dts/omap3.dtsi @@ -0,0 +1,63 @@ +/* + * Device Tree Source for OMAP3 SoC + * + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +/include/ "skeleton.dtsi" + +/ { + compatible = "ti,omap3430", "ti,omap3"; + + cpus { + cpu@0 { + compatible = "arm,cortex-a8"; + }; + }; + + /* + * The soc node represents the soc top level view. It is uses for IPs + * that are not memory mapped in the MPU view or for the MPU itself. + */ + soc { + compatible = "ti,omap-infra"; + mpu { + compatible = "ti,omap3-mpu"; + ti,hwmods = "mpu"; + }; + + iva { + compatible = "ti,iva2.2"; + ti,hwmods = "iva"; + + dsp { + compatible = "ti,omap3-c64"; + }; + }; + }; + + /* + * XXX: Use a flat representation of the OMAP3 interconnect. + * The real OMAP interconnect network is quite complex. + * Since that will not bring real advantage to represent that in DT for + * the moment, just use a fake OCP bus entry to represent the whole bus + * hierarchy. + */ + ocp { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + ti,hwmods = "l3_main"; + + intc: interrupt-controller@1 { + compatible = "ti,omap3-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; +}; diff --git a/arch/arm/boot/dts/omap4-panda.dts b/arch/arm/boot/dts/omap4-panda.dts new file mode 100644 index 0000000000000000000000000000000000000000..c7026578ce7d6ef25b22f167ec5265918a5d6c8b --- /dev/null +++ b/arch/arm/boot/dts/omap4-panda.dts @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ +/dts-v1/; + +/include/ "omap4.dtsi" + +/ { + model = "TI OMAP4 PandaBoard"; + compatible = "ti,omap4-panda", "ti,omap4430", "ti,omap4"; + + /* + * Since the initial device tree board file does not create any + * devices (MMC, network...), the only way to boot is to provide a + * ramdisk. + */ + chosen { + bootargs = "root=/dev/ram0 rw console=ttyO2,115200n8 initrd=0x81600000,20M ramdisk_size=20480 no_console_suspend debug"; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x40000000>; /* 1 GB */ + }; +}; diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts new file mode 100644 index 0000000000000000000000000000000000000000..066e28c90328f252639d4d2c1de6b76e2a497a18 --- /dev/null +++ b/arch/arm/boot/dts/omap4-sdp.dts @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ +/dts-v1/; + +/include/ "omap4.dtsi" + +/ { + model = "TI OMAP4 SDP board"; + compatible = "ti,omap4-sdp", "ti,omap4430", "ti,omap4"; + + /* + * Since the initial device tree board file does not create any + * devices (MMC, network...), the only way to boot is to provide a + * ramdisk. + */ + chosen { + bootargs = "root=/dev/ram0 rw console=ttyO2,115200n8 initrd=0x81600000,20M ramdisk_size=20480 no_console_suspend debug"; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x40000000>; /* 1 GB */ + }; +}; diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..4c61c829043ab4a38f26f791ad998e67a48d5b5d --- /dev/null +++ b/arch/arm/boot/dts/omap4.dtsi @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ + +/* + * Carveout for multimedia usecases + * It should be the last 48MB of the first 512MB memory part + * In theory, it should not even exist. That zone should be reserved + * dynamically during the .reserve callback. + */ +/memreserve/ 0x9d000000 0x03000000; + +/include/ "skeleton.dtsi" + +/ { + compatible = "ti,omap4430", "ti,omap4"; + interrupt-parent = <&gic>; + + aliases { + }; + + cpus { + cpu@0 { + compatible = "arm,cortex-a9"; + }; + cpu@1 { + compatible = "arm,cortex-a9"; + }; + }; + + /* + * The soc node represents the soc top level view. It is uses for IPs + * that are not memory mapped in the MPU view or for the MPU itself. + */ + soc { + compatible = "ti,omap-infra"; + mpu { + compatible = "ti,omap4-mpu"; + ti,hwmods = "mpu"; + }; + + dsp { + compatible = "ti,omap3-c64"; + ti,hwmods = "dsp"; + }; + + iva { + compatible = "ti,ivahd"; + ti,hwmods = "iva"; + }; + }; + + /* + * XXX: Use a flat representation of the OMAP4 interconnect. + * The real OMAP interconnect network is quite complex. + * + * MPU -+-- MPU_PRIVATE - GIC, L2 + * | + * +----------------+----------+ + * | | | + * + +- EMIF - DDR | + * | | | + * | + +--------+ + * | | | + * | +- L4_ABE - AESS, MCBSP, TIMERs... + * | | + * +- L3_MAIN --+- L4_CORE - IPs... + * | + * +- L4_PER - IPs... + * | + * +- L4_CFG -+- L4_WKUP - IPs... + * | | + * | +- IPs... + * +- IPU ----+ + * | | + * +- DSP ----+ + * | | + * +- DSS ----+ + * + * Since that will not bring real advantage to represent that in DT for + * the moment, just use a fake OCP bus entry to represent the whole bus + * hierarchy. + */ + ocp { + compatible = "ti,omap4-l3-noc", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + ti,hwmods = "l3_main_1", "l3_main_2", "l3_main_3"; + + gic: interrupt-controller@48241000 { + compatible = "arm,cortex-a9-gic"; + interrupt-controller; + #interrupt-cells = <1>; + reg = <0x48241000 0x1000>, + <0x48240100 0x0100>; + }; + }; +}; diff --git a/arch/arm/boot/dts/picoxcell-pc3x2.dtsi b/arch/arm/boot/dts/picoxcell-pc3x2.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..f0a8c2068ea7c902641894a5bbddb89e1920ae06 --- /dev/null +++ b/arch/arm/boot/dts/picoxcell-pc3x2.dtsi @@ -0,0 +1,249 @@ +/* + * Copyright (C) 2011 Picochip, Jamie Iles + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ +/include/ "skeleton.dtsi" +/ { + model = "Picochip picoXcell PC3X2"; + compatible = "picochip,pc3x2"; + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + compatible = "arm,1176jz-s"; + clock-frequency = <400000000>; + reg = <0>; + d-cache-line-size = <32>; + d-cache-size = <32768>; + i-cache-line-size = <32>; + i-cache-size = <32768>; + }; + }; + + clocks { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + pclk: clock@0 { + compatible = "fixed-clock"; + clock-outputs = "bus", "pclk"; + clock-frequency = <200000000>; + ref-clock = <&ref_clk>, "ref"; + }; + }; + + paxi { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x80000000 0x400000>; + + emac: gem@30000 { + compatible = "cadence,gem"; + reg = <0x30000 0x10000>; + interrupts = <31>; + }; + + dmac1: dmac@40000 { + compatible = "snps,dw-dmac"; + reg = <0x40000 0x10000>; + interrupts = <25>; + }; + + dmac2: dmac@50000 { + compatible = "snps,dw-dmac"; + reg = <0x50000 0x10000>; + interrupts = <26>; + }; + + vic0: interrupt-controller@60000 { + compatible = "arm,pl192-vic"; + interrupt-controller; + reg = <0x60000 0x1000>; + #interrupt-cells = <1>; + }; + + vic1: interrupt-controller@64000 { + compatible = "arm,pl192-vic"; + interrupt-controller; + reg = <0x64000 0x1000>; + #interrupt-cells = <1>; + }; + + fuse: picoxcell-fuse@80000 { + compatible = "picoxcell,fuse-pc3x2"; + reg = <0x80000 0x10000>; + }; + + ssi: picoxcell-spi@90000 { + compatible = "picoxcell,spi"; + reg = <0x90000 0x10000>; + interrupt-parent = <&vic0>; + interrupts = <10>; + }; + + ipsec: spacc@100000 { + compatible = "picochip,spacc-ipsec"; + reg = <0x100000 0x10000>; + interrupt-parent = <&vic0>; + interrupts = <24>; + ref-clock = <&pclk>, "ref"; + }; + + srtp: spacc@140000 { + compatible = "picochip,spacc-srtp"; + reg = <0x140000 0x10000>; + interrupt-parent = <&vic0>; + interrupts = <23>; + }; + + l2_engine: spacc@180000 { + compatible = "picochip,spacc-l2"; + reg = <0x180000 0x10000>; + interrupt-parent = <&vic0>; + interrupts = <22>; + ref-clock = <&pclk>, "ref"; + }; + + apb { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x200000 0x80000>; + + rtc0: rtc@00000 { + compatible = "picochip,pc3x2-rtc"; + clock-freq = <200000000>; + reg = <0x00000 0xf>; + interrupt-parent = <&vic1>; + interrupts = <8>; + }; + + timer0: timer@10000 { + compatible = "picochip,pc3x2-timer"; + interrupt-parent = <&vic0>; + interrupts = <4>; + clock-freq = <200000000>; + reg = <0x10000 0x14>; + }; + + timer1: timer@10014 { + compatible = "picochip,pc3x2-timer"; + interrupt-parent = <&vic0>; + interrupts = <5>; + clock-freq = <200000000>; + reg = <0x10014 0x14>; + }; + + timer2: timer@10028 { + compatible = "picochip,pc3x2-timer"; + interrupt-parent = <&vic0>; + interrupts = <6>; + clock-freq = <200000000>; + reg = <0x10028 0x14>; + }; + + timer3: timer@1003c { + compatible = "picochip,pc3x2-timer"; + interrupt-parent = <&vic0>; + interrupts = <7>; + clock-freq = <200000000>; + reg = <0x1003c 0x14>; + }; + + gpio: gpio@20000 { + compatible = "snps,dw-apb-gpio"; + reg = <0x20000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + reg-io-width = <4>; + + banka: gpio-controller@0 { + compatible = "snps,dw-apb-gpio-bank"; + gpio-controller; + #gpio-cells = <2>; + gpio-generic,nr-gpio = <8>; + + regoffset-dat = <0x50>; + regoffset-set = <0x00>; + regoffset-dirout = <0x04>; + }; + + bankb: gpio-controller@1 { + compatible = "snps,dw-apb-gpio-bank"; + gpio-controller; + #gpio-cells = <2>; + gpio-generic,nr-gpio = <8>; + + regoffset-dat = <0x54>; + regoffset-set = <0x0c>; + regoffset-dirout = <0x10>; + }; + }; + + uart0: uart@30000 { + compatible = "snps,dw-apb-uart"; + reg = <0x30000 0x1000>; + interrupt-parent = <&vic1>; + interrupts = <10>; + clock-frequency = <3686400>; + reg-shift = <2>; + reg-io-width = <4>; + }; + + uart1: uart@40000 { + compatible = "snps,dw-apb-uart"; + reg = <0x40000 0x1000>; + interrupt-parent = <&vic1>; + interrupts = <9>; + clock-frequency = <3686400>; + reg-shift = <2>; + reg-io-width = <4>; + }; + + wdog: watchdog@50000 { + compatible = "snps,dw-apb-wdg"; + reg = <0x50000 0x10000>; + interrupt-parent = <&vic0>; + interrupts = <11>; + bus-clock = <&pclk>, "bus"; + }; + }; + }; + + rwid-axi { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges; + + ebi@50000000 { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0x40000000 0x08000000 + 1 0 0x48000000 0x08000000 + 2 0 0x50000000 0x08000000 + 3 0 0x58000000 0x08000000>; + }; + + axi2pico@c0000000 { + compatible = "picochip,axi2pico-pc3x2"; + reg = <0xc0000000 0x10000>; + interrupts = <13 14 15 16 17 18 19 20 21>; + }; + }; +}; diff --git a/arch/arm/boot/dts/picoxcell-pc3x3.dtsi b/arch/arm/boot/dts/picoxcell-pc3x3.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..daa962d191e691cab339d778c1a1d6a68a7fb125 --- /dev/null +++ b/arch/arm/boot/dts/picoxcell-pc3x3.dtsi @@ -0,0 +1,365 @@ +/* + * Copyright (C) 2011 Picochip, Jamie Iles + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ +/include/ "skeleton.dtsi" +/ { + model = "Picochip picoXcell PC3X3"; + compatible = "picochip,pc3x3"; + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + compatible = "arm,1176jz-s"; + cpu-clock = <&arm_clk>, "cpu"; + reg = <0>; + d-cache-line-size = <32>; + d-cache-size = <32768>; + i-cache-line-size = <32>; + i-cache-size = <32768>; + }; + }; + + clocks { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + clkgate: clkgate@800a0048 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x800a0048 4>; + compatible = "picochip,pc3x3-clk-gate"; + + tzprot_clk: clock@0 { + compatible = "picochip,pc3x3-gated-clk"; + clock-outputs = "bus"; + picochip,clk-disable-bit = <0>; + clock-frequency = <200000000>; + ref-clock = <&ref_clk>, "ref"; + }; + + spi_clk: clock@1 { + compatible = "picochip,pc3x3-gated-clk"; + clock-outputs = "bus"; + picochip,clk-disable-bit = <1>; + clock-frequency = <200000000>; + ref-clock = <&ref_clk>, "ref"; + }; + + dmac0_clk: clock@2 { + compatible = "picochip,pc3x3-gated-clk"; + clock-outputs = "bus"; + picochip,clk-disable-bit = <2>; + clock-frequency = <200000000>; + ref-clock = <&ref_clk>, "ref"; + }; + + dmac1_clk: clock@3 { + compatible = "picochip,pc3x3-gated-clk"; + clock-outputs = "bus"; + picochip,clk-disable-bit = <3>; + clock-frequency = <200000000>; + ref-clock = <&ref_clk>, "ref"; + }; + + ebi_clk: clock@4 { + compatible = "picochip,pc3x3-gated-clk"; + clock-outputs = "bus"; + picochip,clk-disable-bit = <4>; + clock-frequency = <200000000>; + ref-clock = <&ref_clk>, "ref"; + }; + + ipsec_clk: clock@5 { + compatible = "picochip,pc3x3-gated-clk"; + clock-outputs = "bus"; + picochip,clk-disable-bit = <5>; + clock-frequency = <200000000>; + ref-clock = <&ref_clk>, "ref"; + }; + + l2_clk: clock@6 { + compatible = "picochip,pc3x3-gated-clk"; + clock-outputs = "bus"; + picochip,clk-disable-bit = <6>; + clock-frequency = <200000000>; + ref-clock = <&ref_clk>, "ref"; + }; + + trng_clk: clock@7 { + compatible = "picochip,pc3x3-gated-clk"; + clock-outputs = "bus"; + picochip,clk-disable-bit = <7>; + clock-frequency = <200000000>; + ref-clock = <&ref_clk>, "ref"; + }; + + fuse_clk: clock@8 { + compatible = "picochip,pc3x3-gated-clk"; + clock-outputs = "bus"; + picochip,clk-disable-bit = <8>; + clock-frequency = <200000000>; + ref-clock = <&ref_clk>, "ref"; + }; + + otp_clk: clock@9 { + compatible = "picochip,pc3x3-gated-clk"; + clock-outputs = "bus"; + picochip,clk-disable-bit = <9>; + clock-frequency = <200000000>; + ref-clock = <&ref_clk>, "ref"; + }; + }; + + arm_clk: clock@11 { + compatible = "picochip,pc3x3-pll"; + reg = <0x800a0050 0x8>; + picochip,min-freq = <140000000>; + picochip,max-freq = <700000000>; + ref-clock = <&ref_clk>, "ref"; + clock-outputs = "cpu"; + }; + + pclk: clock@12 { + compatible = "fixed-clock"; + clock-outputs = "bus", "pclk"; + clock-frequency = <200000000>; + ref-clock = <&ref_clk>, "ref"; + }; + }; + + paxi { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x80000000 0x400000>; + + emac: gem@30000 { + compatible = "cadence,gem"; + reg = <0x30000 0x10000>; + interrupt-parent = <&vic0>; + interrupts = <31>; + }; + + dmac1: dmac@40000 { + compatible = "snps,dw-dmac"; + reg = <0x40000 0x10000>; + interrupt-parent = <&vic0>; + interrupts = <25>; + }; + + dmac2: dmac@50000 { + compatible = "snps,dw-dmac"; + reg = <0x50000 0x10000>; + interrupt-parent = <&vic0>; + interrupts = <26>; + }; + + vic0: interrupt-controller@60000 { + compatible = "arm,pl192-vic"; + interrupt-controller; + reg = <0x60000 0x1000>; + #interrupt-cells = <1>; + }; + + vic1: interrupt-controller@64000 { + compatible = "arm,pl192-vic"; + interrupt-controller; + reg = <0x64000 0x1000>; + #interrupt-cells = <1>; + }; + + fuse: picoxcell-fuse@80000 { + compatible = "picoxcell,fuse-pc3x3"; + reg = <0x80000 0x10000>; + }; + + ssi: picoxcell-spi@90000 { + compatible = "picoxcell,spi"; + reg = <0x90000 0x10000>; + interrupt-parent = <&vic0>; + interrupts = <10>; + }; + + ipsec: spacc@100000 { + compatible = "picochip,spacc-ipsec"; + reg = <0x100000 0x10000>; + interrupt-parent = <&vic0>; + interrupts = <24>; + ref-clock = <&ipsec_clk>, "ref"; + }; + + srtp: spacc@140000 { + compatible = "picochip,spacc-srtp"; + reg = <0x140000 0x10000>; + interrupt-parent = <&vic0>; + interrupts = <23>; + }; + + l2_engine: spacc@180000 { + compatible = "picochip,spacc-l2"; + reg = <0x180000 0x10000>; + interrupt-parent = <&vic0>; + interrupts = <22>; + ref-clock = <&l2_clk>, "ref"; + }; + + apb { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x200000 0x80000>; + + rtc0: rtc@00000 { + compatible = "picochip,pc3x2-rtc"; + clock-freq = <200000000>; + reg = <0x00000 0xf>; + interrupt-parent = <&vic0>; + interrupts = <8>; + }; + + timer0: timer@10000 { + compatible = "picochip,pc3x2-timer"; + interrupt-parent = <&vic0>; + interrupts = <4>; + clock-freq = <200000000>; + reg = <0x10000 0x14>; + }; + + timer1: timer@10014 { + compatible = "picochip,pc3x2-timer"; + interrupt-parent = <&vic0>; + interrupts = <5>; + clock-freq = <200000000>; + reg = <0x10014 0x14>; + }; + + gpio: gpio@20000 { + compatible = "snps,dw-apb-gpio"; + reg = <0x20000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + reg-io-width = <4>; + + banka: gpio-controller@0 { + compatible = "snps,dw-apb-gpio-bank"; + gpio-controller; + #gpio-cells = <2>; + gpio-generic,nr-gpio = <8>; + + regoffset-dat = <0x50>; + regoffset-set = <0x00>; + regoffset-dirout = <0x04>; + }; + + bankb: gpio-controller@1 { + compatible = "snps,dw-apb-gpio-bank"; + gpio-controller; + #gpio-cells = <2>; + gpio-generic,nr-gpio = <16>; + + regoffset-dat = <0x54>; + regoffset-set = <0x0c>; + regoffset-dirout = <0x10>; + }; + + bankd: gpio-controller@2 { + compatible = "snps,dw-apb-gpio-bank"; + gpio-controller; + #gpio-cells = <2>; + gpio-generic,nr-gpio = <30>; + + regoffset-dat = <0x5c>; + regoffset-set = <0x24>; + regoffset-dirout = <0x28>; + }; + }; + + uart0: uart@30000 { + compatible = "snps,dw-apb-uart"; + reg = <0x30000 0x1000>; + interrupt-parent = <&vic1>; + interrupts = <10>; + clock-frequency = <3686400>; + reg-shift = <2>; + reg-io-width = <4>; + }; + + uart1: uart@40000 { + compatible = "snps,dw-apb-uart"; + reg = <0x40000 0x1000>; + interrupt-parent = <&vic1>; + interrupts = <9>; + clock-frequency = <3686400>; + reg-shift = <2>; + reg-io-width = <4>; + }; + + wdog: watchdog@50000 { + compatible = "snps,dw-apb-wdg"; + reg = <0x50000 0x10000>; + interrupt-parent = <&vic0>; + interrupts = <11>; + bus-clock = <&pclk>, "bus"; + }; + + timer2: timer@60000 { + compatible = "picochip,pc3x2-timer"; + interrupt-parent = <&vic0>; + interrupts = <6>; + clock-freq = <200000000>; + reg = <0x60000 0x14>; + }; + + timer3: timer@60014 { + compatible = "picochip,pc3x2-timer"; + interrupt-parent = <&vic0>; + interrupts = <7>; + clock-freq = <200000000>; + reg = <0x60014 0x14>; + }; + }; + }; + + rwid-axi { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges; + + ebi@50000000 { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0x40000000 0x08000000 + 1 0 0x48000000 0x08000000 + 2 0 0x50000000 0x08000000 + 3 0 0x58000000 0x08000000>; + }; + + axi2pico@c0000000 { + compatible = "picochip,axi2pico-pc3x3"; + reg = <0xc0000000 0x10000>; + interrupt-parent = <&vic0>; + interrupts = <13 14 15 16 17 18 19 20 21>; + }; + + otp@ffff8000 { + compatible = "picochip,otp-pc3x3"; + reg = <0xffff8000 0x8000>; + }; + }; +}; diff --git a/arch/arm/boot/dts/picoxcell-pc7302-pc3x2.dts b/arch/arm/boot/dts/picoxcell-pc7302-pc3x2.dts new file mode 100644 index 0000000000000000000000000000000000000000..1297414dd649aabcdf1a47d87708908e9926ee3a --- /dev/null +++ b/arch/arm/boot/dts/picoxcell-pc7302-pc3x2.dts @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2011 Picochip, Jamie Iles + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +/dts-v1/; +/include/ "picoxcell-pc3x2.dtsi" +/ { + model = "Picochip PC7302 (PC3X2)"; + compatible = "picochip,pc7302-pc3x2", "picochip,pc3x2"; + + memory { + device_type = "memory"; + reg = <0x0 0x08000000>; + }; + + chosen { + linux,stdout-path = &uart0; + }; + + clocks { + ref_clk: clock@1 { + compatible = "fixed-clock"; + clock-outputs = "ref"; + clock-frequency = <20000000>; + }; + }; + + rwid-axi { + ebi@50000000 { + nand: gpio-nand@2,0 { + compatible = "gpio-control-nand"; + #address-cells = <1>; + #size-cells = <1>; + reg = <2 0x0000 0x1000>; + bus-clock = <&pclk>, "bus"; + gpio-control-nand,io-sync-reg = + <0x00000000 0x80220000>; + + gpios = <&banka 1 0 /* rdy */ + &banka 2 0 /* nce */ + &banka 3 0 /* ale */ + &banka 4 0 /* cle */ + 0 /* nwp */>; + + boot@100000 { + label = "Boot"; + reg = <0x100000 0x80000>; + }; + + redundant-boot@200000 { + label = "Redundant Boot"; + reg = <0x200000 0x80000>; + }; + + boot-env@300000 { + label = "Boot Evironment"; + reg = <0x300000 0x20000>; + }; + + redundant-boot-env@320000 { + label = "Redundant Boot Environment"; + reg = <0x300000 0x20000>; + }; + + kernel@380000 { + label = "Kernel"; + reg = <0x380000 0x800000>; + }; + + fs@b80000 { + label = "File System"; + reg = <0xb80000 0xf480000>; + }; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/picoxcell-pc7302-pc3x3.dts b/arch/arm/boot/dts/picoxcell-pc7302-pc3x3.dts new file mode 100644 index 0000000000000000000000000000000000000000..9e317a4f431cc9c72d7340cca5c6fc07e61b0993 --- /dev/null +++ b/arch/arm/boot/dts/picoxcell-pc7302-pc3x3.dts @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2011 Picochip, Jamie Iles + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +/dts-v1/; +/include/ "picoxcell-pc3x3.dtsi" +/ { + model = "Picochip PC7302 (PC3X3)"; + compatible = "picochip,pc7302-pc3x3", "picochip,pc3x3"; + + memory { + device_type = "memory"; + reg = <0x0 0x08000000>; + }; + + chosen { + linux,stdout-path = &uart0; + }; + + clocks { + ref_clk: clock@10 { + compatible = "fixed-clock"; + clock-outputs = "ref"; + clock-frequency = <20000000>; + }; + + clkgate: clkgate@800a0048 { + clock@4 { + picochip,clk-no-disable; + }; + }; + }; + + rwid-axi { + ebi@50000000 { + nand: gpio-nand@2,0 { + compatible = "gpio-control-nand"; + #address-cells = <1>; + #size-cells = <1>; + reg = <2 0x0000 0x1000>; + bus-clock = <&ebi_clk>, "bus"; + gpio-control-nand,io-sync-reg = + <0x00000000 0x80220000>; + + gpios = <&banka 1 0 /* rdy */ + &banka 2 0 /* nce */ + &banka 3 0 /* ale */ + &banka 4 0 /* cle */ + 0 /* nwp */>; + + boot@100000 { + label = "Boot"; + reg = <0x100000 0x80000>; + }; + + redundant-boot@200000 { + label = "Redundant Boot"; + reg = <0x200000 0x80000>; + }; + + boot-env@300000 { + label = "Boot Evironment"; + reg = <0x300000 0x20000>; + }; + + redundant-boot-env@320000 { + label = "Redundant Boot Environment"; + reg = <0x300000 0x20000>; + }; + + kernel@380000 { + label = "Kernel"; + reg = <0x380000 0x800000>; + }; + + fs@b80000 { + label = "File System"; + reg = <0xb80000 0xf480000>; + }; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/prima2-cb.dts b/arch/arm/boot/dts/prima2-cb.dts index 6fecc88065b20a8326472b7c19cb204478a30a50..34ae3a64ba255a871791e48d7d6cf9edc723e0e2 100644 --- a/arch/arm/boot/dts/prima2-cb.dts +++ b/arch/arm/boot/dts/prima2-cb.dts @@ -39,9 +39,12 @@ ranges = <0x40000000 0x40000000 0x80000000>; l2-cache-controller@80040000 { - compatible = "arm,pl310-cache"; + compatible = "arm,pl310-cache", "sirf,prima2-pl310-cache"; reg = <0x80040000 0x1000>; interrupts = <59>; + arm,tag-latency = <1 1 1>; + arm,data-latency = <1 1 1>; + arm,filter-ranges = <0 0x40000000>; }; intc: interrupt-controller@80020000 { @@ -67,6 +70,11 @@ compatible = "sirf,prima2-rstc"; reg = <0x88010000 0x1000>; }; + + rsc-controller@88020000 { + compatible = "sirf,prima2-rsc"; + reg = <0x88020000 0x1000>; + }; }; mem-iobg { @@ -274,7 +282,7 @@ gpio: gpio-controller@b0120000 { #gpio-cells = <2>; #interrupt-cells = <2>; - compatible = "sirf,prima2-gpio"; + compatible = "sirf,prima2-gpio-pinmux"; reg = <0xb0120000 0x10000>; gpio-controller; interrupt-controller; @@ -358,7 +366,7 @@ }; rtc-iobg { - compatible = "sirf,prima2-rtciobg", "simple-bus"; + compatible = "sirf,prima2-rtciobg", "sirf-prima2-rtciobg-bus"; #address-cells = <1>; #size-cells = <1>; reg = <0x80030000 0x10000>; diff --git a/arch/arm/boot/dts/tegra-harmony.dts b/arch/arm/boot/dts/tegra-harmony.dts index e5818668d09163a37798d276aa2c9211e936f213..0e225b86b6520ab944432b5ab312e7d3f08813d9 100644 --- a/arch/arm/boot/dts/tegra-harmony.dts +++ b/arch/arm/boot/dts/tegra-harmony.dts @@ -66,5 +66,6 @@ cd-gpios = <&gpio 58 0>; /* gpio PH2 */ wp-gpios = <&gpio 59 0>; /* gpio PH3 */ power-gpios = <&gpio 70 0>; /* gpio PI6 */ + support-8bit; }; }; diff --git a/arch/arm/boot/dts/tegra-seaboard.dts b/arch/arm/boot/dts/tegra-seaboard.dts index 64cedca6fc79c33f14e5aef0e9bdd9dc13b4a629..a72299b8e66857b43c1ac2ec4a2c709df6562b2a 100644 --- a/arch/arm/boot/dts/tegra-seaboard.dts +++ b/arch/arm/boot/dts/tegra-seaboard.dts @@ -25,4 +25,8 @@ wp-gpios = <&gpio 57 0>; /* gpio PH1 */ power-gpios = <&gpio 70 0>; /* gpio PI6 */ }; + + sdhci@c8000600 { + support-8bit; + }; }; diff --git a/arch/arm/boot/dts/tegra-ventana.dts b/arch/arm/boot/dts/tegra-ventana.dts new file mode 100644 index 0000000000000000000000000000000000000000..9b29a623aaf1a4296d45fb8c45c835466617619c --- /dev/null +++ b/arch/arm/boot/dts/tegra-ventana.dts @@ -0,0 +1,32 @@ +/dts-v1/; + +/memreserve/ 0x1c000000 0x04000000; +/include/ "tegra20.dtsi" + +/ { + model = "NVIDIA Tegra2 Ventana evaluation board"; + compatible = "nvidia,ventana", "nvidia,tegra20"; + + chosen { + bootargs = "vmalloc=192M video=tegrafb console=ttyS0,115200n8 root=/dev/ram rdinit=/sbin/init"; + }; + + memory { + reg = < 0x00000000 0x40000000 >; + }; + + serial@70006300 { + clock-frequency = < 216000000 >; + }; + + sdhci@c8000400 { + cd-gpios = <&gpio 69 0>; /* gpio PI5 */ + wp-gpios = <&gpio 57 0>; /* gpio PH1 */ + power-gpios = <&gpio 155 0>; /* gpio PT3 */ + }; + + sdhci@c8000600 { + power-gpios = <&gpio 70 0>; /* gpio PI6 */ + support-8bit; + }; +}; diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi index 5727595cde617480d7e86e0bcc9ac5b047402d7e..65d7e6a333eb8214ae5b21607d325e8db84935e1 100644 --- a/arch/arm/boot/dts/tegra20.dtsi +++ b/arch/arm/boot/dts/tegra20.dtsi @@ -77,6 +77,14 @@ gpio-controller; }; + pinmux: pinmux@70000000 { + compatible = "nvidia,tegra20-pinmux"; + reg = < 0x70000014 0x10 /* Tri-state registers */ + 0x70000080 0x20 /* Mux registers */ + 0x700000a0 0x14 /* Pull-up/down registers */ + 0x70000868 0xa8 >; /* Pad control registers */ + }; + serial@70006000 { compatible = "nvidia,tegra20-uart"; reg = <0x70006000 0x40>; diff --git a/arch/arm/boot/dts/usb_a9g20.dts b/arch/arm/boot/dts/usb_a9g20.dts new file mode 100644 index 0000000000000000000000000000000000000000..d66e2c00ac3507b3c5afdfd791b0ece0eab97bbf --- /dev/null +++ b/arch/arm/boot/dts/usb_a9g20.dts @@ -0,0 +1,30 @@ +/* + * usb_a9g20.dts - Device Tree file for Caloa USB A9G20 board + * + * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD + * + * Licensed under GPLv2 or later. + */ +/dts-v1/; +/include/ "at91sam9g20.dtsi" + +/ { + model = "Calao USB A9G20"; + compatible = "calao,usb-a9g20", "atmel,at91sam9g20", "atmel,at91sam9"; + + chosen { + bootargs = "mem=64M console=ttyS0,115200 mtdparts=atmel_nand:128k(at91bootstrap),256k(barebox)ro,128k(bareboxenv),128k(bareboxenv2),4M(kernel),120M(rootfs),-(data) root=/dev/mtdblock5 rw rootfstype=ubifs"; + }; + + memory@20000000 { + reg = <0x20000000 0x4000000>; + }; + + ahb { + apb { + dbgu: serial@fffff200 { + status = "okay"; + }; + }; + }; +}; diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig index 4b71766fb21ddf51e3764eab92ade6051ac6fe09..74df9ca2be316e2df49f164df3ec680366a41a6b 100644 --- a/arch/arm/common/Kconfig +++ b/arch/arm/common/Kconfig @@ -1,4 +1,5 @@ config ARM_GIC + select IRQ_DOMAIN bool config ARM_VIC diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index 3227ca952a12a16481175650689154ca83d4a602..0e6ae470c94f26589c0721a059dfaded9b2f30b1 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c @@ -24,16 +24,26 @@ */ #include #include +#include +#include #include #include +#include #include #include +#include +#include +#include +#include +#include +#include +#include #include #include #include -static DEFINE_SPINLOCK(irq_controller_lock); +static DEFINE_RAW_SPINLOCK(irq_controller_lock); /* Address of GIC 0 CPU interface */ void __iomem *gic_cpu_base_addr __read_mostly; @@ -71,8 +81,7 @@ static inline void __iomem *gic_cpu_base(struct irq_data *d) static inline unsigned int gic_irq(struct irq_data *d) { - struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d); - return d->irq - gic_data->irq_offset; + return d->hwirq; } /* @@ -80,32 +89,32 @@ static inline unsigned int gic_irq(struct irq_data *d) */ static void gic_mask_irq(struct irq_data *d) { - u32 mask = 1 << (d->irq % 32); + u32 mask = 1 << (gic_irq(d) % 32); - spin_lock(&irq_controller_lock); + raw_spin_lock(&irq_controller_lock); writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4); if (gic_arch_extn.irq_mask) gic_arch_extn.irq_mask(d); - spin_unlock(&irq_controller_lock); + raw_spin_unlock(&irq_controller_lock); } static void gic_unmask_irq(struct irq_data *d) { - u32 mask = 1 << (d->irq % 32); + u32 mask = 1 << (gic_irq(d) % 32); - spin_lock(&irq_controller_lock); + raw_spin_lock(&irq_controller_lock); if (gic_arch_extn.irq_unmask) gic_arch_extn.irq_unmask(d); writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4); - spin_unlock(&irq_controller_lock); + raw_spin_unlock(&irq_controller_lock); } static void gic_eoi_irq(struct irq_data *d) { if (gic_arch_extn.irq_eoi) { - spin_lock(&irq_controller_lock); + raw_spin_lock(&irq_controller_lock); gic_arch_extn.irq_eoi(d); - spin_unlock(&irq_controller_lock); + raw_spin_unlock(&irq_controller_lock); } writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI); @@ -129,7 +138,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type) if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING) return -EINVAL; - spin_lock(&irq_controller_lock); + raw_spin_lock(&irq_controller_lock); if (gic_arch_extn.irq_set_type) gic_arch_extn.irq_set_type(d, type); @@ -154,7 +163,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type) if (enabled) writel_relaxed(enablemask, base + GIC_DIST_ENABLE_SET + enableoff); - spin_unlock(&irq_controller_lock); + raw_spin_unlock(&irq_controller_lock); return 0; } @@ -172,7 +181,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, bool force) { void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3); - unsigned int shift = (d->irq % 4) * 8; + unsigned int shift = (gic_irq(d) % 4) * 8; unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask); u32 val, mask, bit; @@ -180,12 +189,12 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, return -EINVAL; mask = 0xff << shift; - bit = 1 << (cpu + shift); + bit = 1 << (cpu_logical_map(cpu) + shift); - spin_lock(&irq_controller_lock); + raw_spin_lock(&irq_controller_lock); val = readl_relaxed(reg) & ~mask; writel_relaxed(val | bit, reg); - spin_unlock(&irq_controller_lock); + raw_spin_unlock(&irq_controller_lock); return IRQ_SET_MASK_OK; } @@ -215,15 +224,15 @@ static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc) chained_irq_enter(chip, desc); - spin_lock(&irq_controller_lock); + raw_spin_lock(&irq_controller_lock); status = readl_relaxed(chip_data->cpu_base + GIC_CPU_INTACK); - spin_unlock(&irq_controller_lock); + raw_spin_unlock(&irq_controller_lock); gic_irq = (status & 0x3ff); if (gic_irq == 1023) goto out; - cascade_irq = gic_irq + chip_data->irq_offset; + cascade_irq = irq_domain_to_irq(&chip_data->domain, gic_irq); if (unlikely(gic_irq < 32 || gic_irq > 1020 || cascade_irq >= NR_IRQS)) do_bad_IRQ(cascade_irq, desc); else @@ -255,27 +264,25 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) irq_set_chained_handler(irq, gic_handle_cascade_irq); } -static void __init gic_dist_init(struct gic_chip_data *gic, - unsigned int irq_start) +static void __init gic_dist_init(struct gic_chip_data *gic) { - unsigned int gic_irqs, irq_limit, i; + unsigned int i, irq; + u32 cpumask; + unsigned int gic_irqs = gic->gic_irqs; + struct irq_domain *domain = &gic->domain; void __iomem *base = gic->dist_base; - u32 cpumask = 1 << smp_processor_id(); + u32 cpu = 0; +#ifdef CONFIG_SMP + cpu = cpu_logical_map(smp_processor_id()); +#endif + + cpumask = 1 << cpu; cpumask |= cpumask << 8; cpumask |= cpumask << 16; writel_relaxed(0, base + GIC_DIST_CTRL); - /* - * Find out how many interrupts are supported. - * The GIC only supports up to 1020 interrupt sources. - */ - gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f; - gic_irqs = (gic_irqs + 1) * 32; - if (gic_irqs > 1020) - gic_irqs = 1020; - /* * Set all global interrupts to be level triggered, active low. */ @@ -301,20 +308,21 @@ static void __init gic_dist_init(struct gic_chip_data *gic, for (i = 32; i < gic_irqs; i += 32) writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32); - /* - * Limit number of interrupts registered to the platform maximum - */ - irq_limit = gic->irq_offset + gic_irqs; - if (WARN_ON(irq_limit > NR_IRQS)) - irq_limit = NR_IRQS; - /* * Setup the Linux IRQ subsystem. */ - for (i = irq_start; i < irq_limit; i++) { - irq_set_chip_and_handler(i, &gic_chip, handle_fasteoi_irq); - irq_set_chip_data(i, gic); - set_irq_flags(i, IRQF_VALID | IRQF_PROBE); + irq_domain_for_each_irq(domain, i, irq) { + if (i < 32) { + irq_set_percpu_devid(irq); + irq_set_chip_and_handler(irq, &gic_chip, + handle_percpu_devid_irq); + set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN); + } else { + irq_set_chip_and_handler(irq, &gic_chip, + handle_fasteoi_irq); + set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + } + irq_set_chip_data(irq, gic); } writel_relaxed(1, base + GIC_DIST_CTRL); @@ -343,23 +351,270 @@ static void __cpuinit gic_cpu_init(struct gic_chip_data *gic) writel_relaxed(1, base + GIC_CPU_CTRL); } -void __init gic_init(unsigned int gic_nr, unsigned int irq_start, +#ifdef CONFIG_CPU_PM +/* + * Saves the GIC distributor registers during suspend or idle. Must be called + * with interrupts disabled but before powering down the GIC. After calling + * this function, no interrupts will be delivered by the GIC, and another + * platform-specific wakeup source must be enabled. + */ +static void gic_dist_save(unsigned int gic_nr) +{ + unsigned int gic_irqs; + void __iomem *dist_base; + int i; + + if (gic_nr >= MAX_GIC_NR) + BUG(); + + gic_irqs = gic_data[gic_nr].gic_irqs; + dist_base = gic_data[gic_nr].dist_base; + + if (!dist_base) + return; + + for (i = 0; i < DIV_ROUND_UP(gic_irqs, 16); i++) + gic_data[gic_nr].saved_spi_conf[i] = + readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4); + + for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++) + gic_data[gic_nr].saved_spi_target[i] = + readl_relaxed(dist_base + GIC_DIST_TARGET + i * 4); + + for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++) + gic_data[gic_nr].saved_spi_enable[i] = + readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4); +} + +/* + * Restores the GIC distributor registers during resume or when coming out of + * idle. Must be called before enabling interrupts. If a level interrupt + * that occured while the GIC was suspended is still present, it will be + * handled normally, but any edge interrupts that occured will not be seen by + * the GIC and need to be handled by the platform-specific wakeup source. + */ +static void gic_dist_restore(unsigned int gic_nr) +{ + unsigned int gic_irqs; + unsigned int i; + void __iomem *dist_base; + + if (gic_nr >= MAX_GIC_NR) + BUG(); + + gic_irqs = gic_data[gic_nr].gic_irqs; + dist_base = gic_data[gic_nr].dist_base; + + if (!dist_base) + return; + + writel_relaxed(0, dist_base + GIC_DIST_CTRL); + + for (i = 0; i < DIV_ROUND_UP(gic_irqs, 16); i++) + writel_relaxed(gic_data[gic_nr].saved_spi_conf[i], + dist_base + GIC_DIST_CONFIG + i * 4); + + for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++) + writel_relaxed(0xa0a0a0a0, + dist_base + GIC_DIST_PRI + i * 4); + + for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++) + writel_relaxed(gic_data[gic_nr].saved_spi_target[i], + dist_base + GIC_DIST_TARGET + i * 4); + + for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++) + writel_relaxed(gic_data[gic_nr].saved_spi_enable[i], + dist_base + GIC_DIST_ENABLE_SET + i * 4); + + writel_relaxed(1, dist_base + GIC_DIST_CTRL); +} + +static void gic_cpu_save(unsigned int gic_nr) +{ + int i; + u32 *ptr; + void __iomem *dist_base; + void __iomem *cpu_base; + + if (gic_nr >= MAX_GIC_NR) + BUG(); + + dist_base = gic_data[gic_nr].dist_base; + cpu_base = gic_data[gic_nr].cpu_base; + + if (!dist_base || !cpu_base) + return; + + ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_enable); + for (i = 0; i < DIV_ROUND_UP(32, 32); i++) + ptr[i] = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4); + + ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_conf); + for (i = 0; i < DIV_ROUND_UP(32, 16); i++) + ptr[i] = readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4); + +} + +static void gic_cpu_restore(unsigned int gic_nr) +{ + int i; + u32 *ptr; + void __iomem *dist_base; + void __iomem *cpu_base; + + if (gic_nr >= MAX_GIC_NR) + BUG(); + + dist_base = gic_data[gic_nr].dist_base; + cpu_base = gic_data[gic_nr].cpu_base; + + if (!dist_base || !cpu_base) + return; + + ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_enable); + for (i = 0; i < DIV_ROUND_UP(32, 32); i++) + writel_relaxed(ptr[i], dist_base + GIC_DIST_ENABLE_SET + i * 4); + + ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_conf); + for (i = 0; i < DIV_ROUND_UP(32, 16); i++) + writel_relaxed(ptr[i], dist_base + GIC_DIST_CONFIG + i * 4); + + for (i = 0; i < DIV_ROUND_UP(32, 4); i++) + writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4); + + writel_relaxed(0xf0, cpu_base + GIC_CPU_PRIMASK); + writel_relaxed(1, cpu_base + GIC_CPU_CTRL); +} + +static int gic_notifier(struct notifier_block *self, unsigned long cmd, void *v) +{ + int i; + + for (i = 0; i < MAX_GIC_NR; i++) { + switch (cmd) { + case CPU_PM_ENTER: + gic_cpu_save(i); + break; + case CPU_PM_ENTER_FAILED: + case CPU_PM_EXIT: + gic_cpu_restore(i); + break; + case CPU_CLUSTER_PM_ENTER: + gic_dist_save(i); + break; + case CPU_CLUSTER_PM_ENTER_FAILED: + case CPU_CLUSTER_PM_EXIT: + gic_dist_restore(i); + break; + } + } + + return NOTIFY_OK; +} + +static struct notifier_block gic_notifier_block = { + .notifier_call = gic_notifier, +}; + +static void __init gic_pm_init(struct gic_chip_data *gic) +{ + gic->saved_ppi_enable = __alloc_percpu(DIV_ROUND_UP(32, 32) * 4, + sizeof(u32)); + BUG_ON(!gic->saved_ppi_enable); + + gic->saved_ppi_conf = __alloc_percpu(DIV_ROUND_UP(32, 16) * 4, + sizeof(u32)); + BUG_ON(!gic->saved_ppi_conf); + + cpu_pm_register_notifier(&gic_notifier_block); +} +#else +static void __init gic_pm_init(struct gic_chip_data *gic) +{ +} +#endif + +#ifdef CONFIG_OF +static int gic_irq_domain_dt_translate(struct irq_domain *d, + struct device_node *controller, + const u32 *intspec, unsigned int intsize, + unsigned long *out_hwirq, unsigned int *out_type) +{ + if (d->of_node != controller) + return -EINVAL; + if (intsize < 3) + return -EINVAL; + + /* Get the interrupt number and add 16 to skip over SGIs */ + *out_hwirq = intspec[1] + 16; + + /* For SPIs, we need to add 16 more to get the GIC irq ID number */ + if (!intspec[0]) + *out_hwirq += 16; + + *out_type = intspec[2] & IRQ_TYPE_SENSE_MASK; + return 0; +} +#endif + +const struct irq_domain_ops gic_irq_domain_ops = { +#ifdef CONFIG_OF + .dt_translate = gic_irq_domain_dt_translate, +#endif +}; + +void __init gic_init(unsigned int gic_nr, int irq_start, void __iomem *dist_base, void __iomem *cpu_base) { struct gic_chip_data *gic; + struct irq_domain *domain; + int gic_irqs; BUG_ON(gic_nr >= MAX_GIC_NR); gic = &gic_data[gic_nr]; + domain = &gic->domain; gic->dist_base = dist_base; gic->cpu_base = cpu_base; - gic->irq_offset = (irq_start - 1) & ~31; - if (gic_nr == 0) + /* + * For primary GICs, skip over SGIs. + * For secondary GICs, skip over PPIs, too. + */ + if (gic_nr == 0) { gic_cpu_base_addr = cpu_base; + domain->hwirq_base = 16; + if (irq_start > 0) + irq_start = (irq_start & ~31) + 16; + } else + domain->hwirq_base = 32; + + /* + * Find out how many interrupts are supported. + * The GIC only supports up to 1020 interrupt sources. + */ + gic_irqs = readl_relaxed(dist_base + GIC_DIST_CTR) & 0x1f; + gic_irqs = (gic_irqs + 1) * 32; + if (gic_irqs > 1020) + gic_irqs = 1020; + gic->gic_irqs = gic_irqs; + + domain->nr_irq = gic_irqs - domain->hwirq_base; + domain->irq_base = irq_alloc_descs(irq_start, 16, domain->nr_irq, + numa_node_id()); + if (IS_ERR_VALUE(domain->irq_base)) { + WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n", + irq_start); + domain->irq_base = irq_start; + } + domain->priv = gic; + domain->ops = &gic_irq_domain_ops; + irq_domain_add(domain); - gic_dist_init(gic, irq_start); + gic_chip.flags |= gic_arch_extn.flags; + gic_dist_init(gic); gic_cpu_init(gic); + gic_pm_init(gic); } void __cpuinit gic_secondary_init(unsigned int gic_nr) @@ -369,20 +624,15 @@ void __cpuinit gic_secondary_init(unsigned int gic_nr) gic_cpu_init(&gic_data[gic_nr]); } -void __cpuinit gic_enable_ppi(unsigned int irq) -{ - unsigned long flags; - - local_irq_save(flags); - irq_set_status_flags(irq, IRQ_NOPROBE); - gic_unmask_irq(irq_get_irq_data(irq)); - local_irq_restore(flags); -} - #ifdef CONFIG_SMP void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) { - unsigned long map = *cpus_addr(*mask); + int cpu; + unsigned long map = 0; + + /* Convert our logical CPU mask into a physical one. */ + for_each_cpu(cpu, mask) + map |= 1 << cpu_logical_map(cpu); /* * Ensure that stores to Normal memory are visible to the @@ -394,3 +644,35 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT); } #endif + +#ifdef CONFIG_OF +static int gic_cnt __initdata = 0; + +int __init gic_of_init(struct device_node *node, struct device_node *parent) +{ + void __iomem *cpu_base; + void __iomem *dist_base; + int irq; + struct irq_domain *domain = &gic_data[gic_cnt].domain; + + if (WARN_ON(!node)) + return -ENODEV; + + dist_base = of_iomap(node, 0); + WARN(!dist_base, "unable to map gic dist registers\n"); + + cpu_base = of_iomap(node, 1); + WARN(!cpu_base, "unable to map gic cpu registers\n"); + + domain->of_node = of_node_get(node); + + gic_init(gic_cnt, -1, dist_base, cpu_base); + + if (parent) { + irq = irq_of_parse_and_map(node, 0); + gic_cascade_irq(gic_cnt, irq); + } + gic_cnt++; + return 0; +} +#endif diff --git a/arch/arm/common/pl330.c b/arch/arm/common/pl330.c index 97912fa48782563527a3b56cc9b60c1acee008f3..7129cfbdacd6887920cf28994625be7b35f65503 100644 --- a/arch/arm/common/pl330.c +++ b/arch/arm/common/pl330.c @@ -1546,7 +1546,7 @@ int pl330_chan_ctrl(void *ch_id, enum pl330_chan_op op) /* Start the next */ case PL330_OP_START: - if (!_start(thrd)) + if (!_thrd_active(thrd) && !_start(thrd)) ret = -EIO; break; diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c index 0569de6acfba66752b53bf9dd34ba213b47e5d11..61691cdbdcf2cd7b7308c10560a917481c0e0be7 100644 --- a/arch/arm/common/sa1111.c +++ b/arch/arm/common/sa1111.c @@ -718,6 +718,10 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq) goto err_free; } + ret = clk_prepare(sachip->clk); + if (ret) + goto err_clkput; + spin_lock_init(&sachip->lock); sachip->dev = me; @@ -733,7 +737,7 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq) sachip->base = ioremap(mem->start, PAGE_SIZE * 2); if (!sachip->base) { ret = -ENOMEM; - goto err_clkput; + goto err_clk_unprep; } /* @@ -809,6 +813,8 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq) err_unmap: iounmap(sachip->base); + err_clk_unprep: + clk_unprepare(sachip->clk); err_clkput: clk_put(sachip->clk); err_free: @@ -835,6 +841,7 @@ static void __sa1111_remove(struct sa1111 *sachip) sa1111_writel(0, irqbase + SA1111_WAKEEN1); clk_disable(sachip->clk); + clk_unprepare(sachip->clk); if (sachip->irq != NO_IRQ) { irq_set_chained_handler(sachip->irq, NULL); diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c index a07b0e763a805109c007161d46efd6df5f45d6b6..1cde34a080d7e688efbf019aae2e55f8e20895c2 100644 --- a/arch/arm/common/scoop.c +++ b/arch/arm/common/scoop.c @@ -12,11 +12,11 @@ */ #include +#include #include #include #include #include -#include #include /* PCMCIA to Scoop linkage diff --git a/arch/arm/common/timer-sp.c b/arch/arm/common/timer-sp.c index 41df47875122a6fcd641a3c47df9ce1de696ce30..2393b5bc96fa12845846bffe613a01c61db176b2 100644 --- a/arch/arm/common/timer-sp.c +++ b/arch/arm/common/timer-sp.c @@ -41,9 +41,17 @@ static long __init sp804_get_clock_rate(const char *name) return PTR_ERR(clk); } + err = clk_prepare(clk); + if (err) { + pr_err("sp804: %s clock failed to prepare: %d\n", name, err); + clk_put(clk); + return err; + } + err = clk_enable(clk); if (err) { pr_err("sp804: %s clock failed to enable: %d\n", name, err); + clk_unprepare(clk); clk_put(clk); return err; } @@ -52,6 +60,7 @@ static long __init sp804_get_clock_rate(const char *name) if (rate < 0) { pr_err("sp804: %s clock failed to get rate: %ld\n", name, rate); clk_disable(clk); + clk_unprepare(clk); clk_put(clk); } diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c index 197f81c77351d8ea1b9bb090781ebc8bf6e0f9a7..01f18a421b17c6e20c6b0bf07a10c75378accc02 100644 --- a/arch/arm/common/vic.c +++ b/arch/arm/common/vic.c @@ -346,7 +346,8 @@ void __init vic_init(void __iomem *base, unsigned int irq_start, /* Identify which VIC cell this one is, by reading the ID */ for (i = 0; i < 4; i++) { - u32 addr = ((u32)base & PAGE_MASK) + 0xfe0 + (i * 4); + void __iomem *addr; + addr = (void __iomem *)((u32)base & PAGE_MASK) + 0xfe0 + (i * 4); cellid |= (readl(addr) & 0xff) << (8 * i); } vendor = (cellid >> 12) & 0xff; diff --git a/arch/arm/configs/at91sam9g45_defconfig b/arch/arm/configs/at91sam9g45_defconfig new file mode 100644 index 0000000000000000000000000000000000000000..c5876d244f4b2d667db3d4753bdc1bdab1203064 --- /dev/null +++ b/arch/arm/configs/at91sam9g45_defconfig @@ -0,0 +1,214 @@ +CONFIG_EXPERIMENTAL=y +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_EMBEDDED=y +CONFIG_SLAB=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_LBDAF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_ARCH_AT91=y +CONFIG_ARCH_AT91SAM9G45=y +CONFIG_MACH_AT91SAM9M10G45EK=y +CONFIG_AT91_PROGRAMMABLE_CLOCKS=y +CONFIG_AT91_SLOW_CLOCK=y +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +CONFIG_LEDS=y +CONFIG_LEDS_CPU=y +CONFIG_UACCESS_WITH_MEMCPY=y +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="mem=128M console=ttyS0,115200 initrd=0x71100000,25165824 root=/dev/ram0 rw" +CONFIG_AUTO_ZRELADDR=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=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 is not set +CONFIG_IPV6=y +# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET6_XFRM_MODE_TUNNEL is not set +# CONFIG_INET6_XFRM_MODE_BEET is not set +CONFIG_IPV6_SIT_6RD=y +CONFIG_CFG80211=y +CONFIG_LIB80211=y +CONFIG_MAC80211=y +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_STANDALONE is not set +# CONFIG_PREVENT_FIRMWARE_BUILD is not set +CONFIG_MTD=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_DATAFLASH=y +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_ATMEL=y +CONFIG_MTD_UBI=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=4 +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_MISC_DEVICES=y +CONFIG_ATMEL_PWM=y +CONFIG_ATMEL_TCLIB=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_NETDEVICES=y +CONFIG_MII=y +CONFIG_DAVICOM_PHY=y +CONFIG_NET_ETHERNET=y +CONFIG_MACB=y +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +CONFIG_LIBERTAS_THINFIRM=m +CONFIG_LIBERTAS_THINFIRM_USB=m +CONFIG_AT76C50X_USB=m +CONFIG_USB_ZD1201=m +CONFIG_RTL8187=m +CONFIG_ATH_COMMON=m +CONFIG_ATH9K=m +CONFIG_CARL9170=m +CONFIG_B43=m +CONFIG_B43_PHY_N=y +CONFIG_LIBERTAS=m +CONFIG_LIBERTAS_USB=m +CONFIG_LIBERTAS_SDIO=m +CONFIG_LIBERTAS_SPI=m +CONFIG_RT2X00=m +CONFIG_RT2500USB=m +CONFIG_RT73USB=m +CONFIG_RT2800USB=m +CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_UNKNOWN=y +CONFIG_RTL8192CU=m +CONFIG_WL1251=m +CONFIG_WL1251_SDIO=m +CONFIG_WL12XX_MENU=m +CONFIG_WL12XX=m +CONFIG_WL12XX_SDIO=m +CONFIG_ZD1211RW=m +CONFIG_MWIFIEX=m +CONFIG_MWIFIEX_SDIO=m +CONFIG_INPUT_POLLDEV=m +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=480 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=272 +CONFIG_INPUT_JOYDEV=y +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +CONFIG_KEYBOARD_QT1070=m +CONFIG_KEYBOARD_QT2160=m +CONFIG_KEYBOARD_GPIO=y +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ATMEL_MXT=m +CONFIG_TOUCHSCREEN_ATMEL_TSADCC=y +# CONFIG_SERIO is not set +CONFIG_LEGACY_PTY_COUNT=4 +CONFIG_SERIAL_ATMEL=y +CONFIG_SERIAL_ATMEL_CONSOLE=y +CONFIG_HW_RANDOM=y +CONFIG_I2C=y +CONFIG_I2C_GPIO=y +CONFIG_SPI=y +CONFIG_SPI_ATMEL=y +# CONFIG_HWMON is not set +# CONFIG_MFD_SUPPORT is not set +CONFIG_FB=y +CONFIG_FB_ATMEL=y +CONFIG_FB_UDL=m +CONFIG_BACKLIGHT_LCD_SUPPORT=y +# CONFIG_LCD_CLASS_DEVICE is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_ATMEL_LCDC=y +# CONFIG_BACKLIGHT_GENERIC is not set +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_SEQUENCER=y +CONFIG_SND_MIXER_OSS=y +CONFIG_SND_PCM_OSS=y +# CONFIG_SND_SUPPORT_OLD_API is not set +# CONFIG_SND_VERBOSE_PROCFS is not set +# CONFIG_SND_DRIVERS is not set +# CONFIG_SND_ARM is not set +CONFIG_SND_ATMEL_AC97C=y +# CONFIG_SND_SPI is not set +CONFIG_SND_USB_AUDIO=m +# CONFIG_USB_HID is not set +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_DEVICE_CLASS is not set +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_ACM=y +CONFIG_USB_STORAGE=y +CONFIG_USB_GADGET=y +CONFIG_USB_ATMEL_USBA=m +CONFIG_USB_ZERO=m +CONFIG_USB_AUDIO=m +CONFIG_USB_ETH=m +CONFIG_USB_ETH_EEM=y +CONFIG_USB_MASS_STORAGE=m +CONFIG_USB_G_SERIAL=m +CONFIG_USB_CDC_COMPOSITE=m +CONFIG_USB_G_MULTI=m +CONFIG_USB_G_MULTI_CDC=y +CONFIG_MMC=y +# CONFIG_MMC_BLOCK_BOUNCE is not set +CONFIG_SDIO_UART=m +CONFIG_MMC_ATMELMCI=y +CONFIG_MMC_ATMELMCI_DMA=y +CONFIG_LEDS_ATMEL_PWM=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_GPIO=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_AT91RM9200=y +CONFIG_DMADEVICES=y +CONFIG_AT_HDMAC=y +CONFIG_DMATEST=m +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_EXT2_FS=y +CONFIG_FANOTIFY=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_SUMMARY=y +CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +CONFIG_SQUASHFS_EMBEDDED=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_850=y +CONFIG_NLS_ISO8859_1=y +CONFIG_STRIP_ASM_SYMS=y +# CONFIG_SCHED_DEBUG is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_FTRACE is not set +CONFIG_DEBUG_USER=y +CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_USER_API_HASH=m +CONFIG_CRYPTO_USER_API_SKCIPHER=m +# CONFIG_CRYPTO_HW is not set diff --git a/arch/arm/configs/exynos4_defconfig b/arch/arm/configs/exynos4_defconfig index da53ff3b4d708122668cf2a910ae0f72ce9f4746..cd40bb56e5686c58b5c2ad7beab4a2105842d897 100644 --- a/arch/arm/configs/exynos4_defconfig +++ b/arch/arm/configs/exynos4_defconfig @@ -11,6 +11,7 @@ CONFIG_MACH_SMDKV310=y CONFIG_MACH_ARMLEX4210=y CONFIG_MACH_UNIVERSAL_C210=y CONFIG_MACH_NURI=y +CONFIG_MACH_ORIGEN=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y diff --git a/arch/arm/configs/mx27_defconfig b/arch/arm/configs/imx_v4_v5_defconfig similarity index 69% rename from arch/arm/configs/mx27_defconfig rename to arch/arm/configs/imx_v4_v5_defconfig index 9ad4c656c9bdf91bdfaf5492bad7ad5d43407a73..11a4192197c8fbaef84a10a53ce24fb497ae3947 100644 --- a/arch/arm/configs/mx27_defconfig +++ b/arch/arm/configs/imx_v4_v5_defconfig @@ -3,9 +3,7 @@ CONFIG_EXPERIMENTAL=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_EXPERT=y -CONFIG_KALLSYMS_EXTRA_PASS=y # CONFIG_COMPAT_BRK is not set CONFIG_SLAB=y CONFIG_PROFILING=y @@ -17,8 +15,12 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_IOSCHED_DEADLINE is not set # CONFIG_IOSCHED_CFQ is not set CONFIG_ARCH_MXC=y -CONFIG_ARCH_MX2=y -CONFIG_MACH_MX27=y +CONFIG_ARCH_IMX_V4_V5=y +CONFIG_ARCH_MX1ADS=y +CONFIG_MACH_SCB9328=y +CONFIG_MACH_MX21ADS=y +CONFIG_MACH_MX25_3DS=y +CONFIG_MACH_EUKREA_CPUIMX25=y CONFIG_MACH_MX27ADS=y CONFIG_MACH_PCM038=y CONFIG_MACH_CPUIMX27=y @@ -29,6 +31,7 @@ CONFIG_MACH_IMX27_VISSTRIM_M10=y CONFIG_MACH_IMX27LITE=y CONFIG_MACH_PCA100=y CONFIG_MACH_MXT_TD60=y +CONFIG_MACH_IMX27IPCAM=y CONFIG_MXC_IRQ_PRIOR=y CONFIG_MXC_PWM=y CONFIG_NO_HZ=y @@ -39,7 +42,6 @@ CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_FPE_NWFPE=y CONFIG_FPE_NWFPE_XP=y -CONFIG_PM=y CONFIG_PM_DEBUG=y CONFIG_NET=y CONFIG_PACKET=y @@ -55,8 +57,9 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_INET_DIAG is not set # CONFIG_IPV6 is not set CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y CONFIG_MTD=y -CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y @@ -69,12 +72,15 @@ CONFIG_MTD_CFI_GEOMETRY=y CONFIG_MTD_CFI_INTELEXT=y CONFIG_MTD_PHYSMAP=y CONFIG_MTD_NAND=y -CONFIG_MTD_NAND_MXC=y CONFIG_MTD_UBI=y +CONFIG_MISC_DEVICES=y CONFIG_EEPROM_AT24=y +CONFIG_EEPROM_AT25=y CONFIG_NETDEVICES=y CONFIG_NET_ETHERNET=y -CONFIG_FEC=y +CONFIG_SMC91X=y +CONFIG_DM9000=y +CONFIG_SMC911X=y # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set # CONFIG_INPUT_MOUSEDEV is not set @@ -84,10 +90,10 @@ CONFIG_INPUT_EVDEV=y CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_ADS7846=m # CONFIG_SERIO is not set +# CONFIG_LEGACY_PTYS is not set CONFIG_SERIAL_8250=m CONFIG_SERIAL_IMX=y CONFIG_SERIAL_IMX_CONSOLE=y -# CONFIG_LEGACY_PTYS is not set # CONFIG_HW_RANDOM is not set CONFIG_I2C=y CONFIG_I2C_CHARDEV=y @@ -98,19 +104,56 @@ CONFIG_W1=y CONFIG_W1_MASTER_MXC=y CONFIG_W1_SLAVE_THERM=y # CONFIG_HWMON is not set +CONFIG_WATCHDOG=y +CONFIG_IMX2_WDT=y +CONFIG_MFD_MC13XXX=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_MC13783=y +CONFIG_REGULATOR_MC13892=y CONFIG_FB=y CONFIG_FB_IMX=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_LCD_CLASS_DEVICE=y +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_PWM=y CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_FONTS=y CONFIG_FONT_8x8=y -# CONFIG_HID_SUPPORT is not set -CONFIG_USB=m +CONFIG_LOGO=y +CONFIG_SOUND=y +CONFIG_SND=y +# CONFIG_SND_ARM is not set +# CONFIG_SND_SPI is not set +CONFIG_SND_SOC=y +CONFIG_SND_IMX_SOC=y +CONFIG_SND_SOC_MX27VIS_AIC32X4=y +CONFIG_SND_SOC_PHYCORE_AC97=y +CONFIG_SND_SOC_EUKREA_TLV320=y +CONFIG_USB_HID=m +CONFIG_USB=y # CONFIG_USB_DEVICE_CLASS is not set +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_MXC=y CONFIG_USB_ULPI=y CONFIG_MMC=y CONFIG_MMC_MXC=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_MC13783=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_BACKLIGHT=y +CONFIG_LEDS_TRIGGER_GPIO=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_PCF8563=y +CONFIG_RTC_DRV_IMXDI=y +CONFIG_RTC_MXC=y +CONFIG_DMADEVICES=y +CONFIG_IMX_SDMA=y +CONFIG_IMX_DMA=y +# CONFIG_IOMMU_SUPPORT is not set # CONFIG_DNOTIFY is not set # CONFIG_PROC_PAGE_MONITOR is not set CONFIG_TMPFS=y @@ -119,12 +162,9 @@ CONFIG_UBIFS_FS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y CONFIG_ROOT_NFS=y -CONFIG_NLS=y CONFIG_NLS_CODEPAGE_437=m CONFIG_NLS_CODEPAGE_850=m CONFIG_NLS_ISO8859_1=y CONFIG_NLS_ISO8859_15=m -CONFIG_DEBUG_FS=y -# CONFIG_RCU_CPU_STALL_DETECTOR is not set CONFIG_SYSCTL_SYSCALL_CHECK=y # CONFIG_CRYPTO_ANSI_CPRNG is not set diff --git a/arch/arm/configs/integrator_defconfig b/arch/arm/configs/integrator_defconfig index 7196ade07e27292a584cd8128aada4c1ce78b413..1103f62a1964e86b799534af2ebd0c535bc64854 100644 --- a/arch/arm/configs/integrator_defconfig +++ b/arch/arm/configs/integrator_defconfig @@ -1,5 +1,6 @@ CONFIG_EXPERIMENTAL=y CONFIG_SYSVIPC=y +CONFIG_TINY_RCU=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 @@ -8,20 +9,29 @@ CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_ARCH_INTEGRATOR=y CONFIG_ARCH_INTEGRATOR_AP=y +CONFIG_ARCH_INTEGRATOR_CP=y CONFIG_CPU_ARM720T=y CONFIG_CPU_ARM920T=y +CONFIG_CPU_ARM922T=y +CONFIG_CPU_ARM926T=y +CONFIG_CPU_ARM1020=y +CONFIG_CPU_ARM1022=y +CONFIG_CPU_ARM1026=y CONFIG_PCI=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_PREEMPT=y +CONFIG_AEABI=y CONFIG_LEDS=y CONFIG_LEDS_CPU=y CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="console=ttyAM0,38400n8 root=/dev/nfs ip=bootp mem=32M" +CONFIG_CMDLINE="console=ttyAM0,38400n8 root=/dev/nfs ip=bootp" CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_GOV_POWERSAVE=y CONFIG_CPU_FREQ_GOV_USERSPACE=y CONFIG_CPU_FREQ_GOV_ONDEMAND=y CONFIG_FPE_NWFPE=y -CONFIG_PM=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y @@ -32,7 +42,6 @@ CONFIG_IP_PNP_DHCP=y CONFIG_IP_PNP_BOOTP=y # CONFIG_IPV6 is not set CONFIG_MTD=y -CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_AFS_PARTS=y CONFIG_MTD_CHAR=y @@ -40,6 +49,7 @@ CONFIG_MTD_BLOCK=y CONFIG_MTD_CFI=y CONFIG_MTD_CFI_ADV_OPTIONS=y CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_PHYSMAP=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=8192 @@ -56,6 +66,8 @@ CONFIG_FB_MODE_HELPERS=y CONFIG_FB_MATROX=y CONFIG_FB_MATROX_MILLENIUM=y CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_PL030=y CONFIG_EXT2_FS=y CONFIG_TMPFS=y CONFIG_JFFS2_FS=y @@ -68,4 +80,3 @@ CONFIG_NFSD_V3=y CONFIG_PARTITION_ADVANCED=y CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_KERNEL=y -CONFIG_DEBUG_ERRORS=y diff --git a/arch/arm/configs/mx1_defconfig b/arch/arm/configs/mx1_defconfig deleted file mode 100644 index c9436d0bf59347ef5d19946926dc20d632dd3229..0000000000000000000000000000000000000000 --- a/arch/arm/configs/mx1_defconfig +++ /dev/null @@ -1,91 +0,0 @@ -CONFIG_EXPERIMENTAL=y -CONFIG_SYSVIPC=y -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_SYSFS_DEPRECATED_V2=y -CONFIG_EXPERT=y -CONFIG_SLAB=y -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_MODVERSIONS=y -# CONFIG_BLK_DEV_BSG is not set -CONFIG_ARCH_MXC=y -CONFIG_ARCH_MX1=y -CONFIG_ARCH_MX1ADS=y -CONFIG_MACH_SCB9328=y -CONFIG_MACH_APF9328=y -CONFIG_MXC_IRQ_PRIOR=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_PREEMPT=y -CONFIG_AEABI=y -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/mtdblock2 rw ip=off" -CONFIG_PM=y -CONFIG_PM_DEBUG=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=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_LRO is not set -# CONFIG_INET_DIAG is not set -# CONFIG_IPV6 is not set -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_FW_LOADER=m -CONFIG_MTD=y -CONFIG_MTD_PARTITIONS=y -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -CONFIG_MTD_CFI=y -CONFIG_MTD_PHYSMAP=y -# CONFIG_BLK_DEV is not set -# CONFIG_MISC_DEVICES is not set -CONFIG_NETDEVICES=y -CONFIG_PHYLIB=y -CONFIG_SMSC_PHY=y -CONFIG_NET_ETHERNET=y -CONFIG_DM9000=y -# CONFIG_NETDEV_1000 is not set -# CONFIG_NETDEV_10000 is not set -# CONFIG_INPUT is not set -# CONFIG_SERIO is not set -# CONFIG_VT is not set -CONFIG_SERIAL_IMX=y -CONFIG_SERIAL_IMX_CONSOLE=y -# CONFIG_LEGACY_PTYS is not set -# CONFIG_HW_RANDOM is not set -CONFIG_I2C=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_IMX=y -CONFIG_W1=y -CONFIG_W1_MASTER_MXC=y -CONFIG_W1_SLAVE_THERM=y -# CONFIG_HWMON is not set -CONFIG_FB=y -CONFIG_USB_GADGET=y -CONFIG_USB_GADGET_IMX=y -CONFIG_USB_ETH=m -CONFIG_MMC=y -CONFIG_MMC_MXC=y -# CONFIG_DNOTIFY is not set -CONFIG_INOTIFY=y -CONFIG_TMPFS=y -CONFIG_JFFS2_FS=y -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -CONFIG_NFS_V4=y -CONFIG_ROOT_NFS=y -# CONFIG_ENABLE_WARN_DEPRECATED is not set -# CONFIG_ENABLE_MUST_CHECK is not set -# CONFIG_RCU_CPU_STALL_DETECTOR is not set -CONFIG_SYSCTL_SYSCALL_CHECK=y -# CONFIG_CRYPTO_ANSI_CPRNG is not set diff --git a/arch/arm/configs/mx21_defconfig b/arch/arm/configs/mx21_defconfig deleted file mode 100644 index 411f88dd440254293204de7a2023c777f4d11ec9..0000000000000000000000000000000000000000 --- a/arch/arm/configs/mx21_defconfig +++ /dev/null @@ -1,97 +0,0 @@ -CONFIG_EXPERIMENTAL=y -# CONFIG_SWAP is not set -CONFIG_SYSVIPC=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_SYSFS_DEPRECATED_V2=y -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_EXPERT=y -CONFIG_KALLSYMS_EXTRA_PASS=y -CONFIG_SLAB=y -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_IOSCHED_DEADLINE is not set -# CONFIG_IOSCHED_CFQ is not set -CONFIG_ARCH_MXC=y -CONFIG_ARCH_MX2=y -CONFIG_MACH_MX21ADS=y -CONFIG_MXC_PWM=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_PREEMPT=y -CONFIG_AEABI=y -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_NET=y -CONFIG_INET=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set -# CONFIG_INET_LRO is not set -# CONFIG_INET_DIAG is not set -# CONFIG_IPV6 is not set -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -# CONFIG_FW_LOADER is not set -CONFIG_MTD=y -CONFIG_MTD_DEBUG=y -CONFIG_MTD_DEBUG_VERBOSE=3 -CONFIG_MTD_PARTITIONS=y -CONFIG_MTD_REDBOOT_PARTS=y -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -CONFIG_MTD_CFI=y -CONFIG_MTD_CFI_ADV_OPTIONS=y -CONFIG_MTD_CFI_GEOMETRY=y -# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set -CONFIG_MTD_CFI_AMDSTD=y -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_NAND=y -CONFIG_MTD_NAND_MXC=y -CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y -CONFIG_MII=y -# CONFIG_NETDEV_1000 is not set -# CONFIG_NETDEV_10000 is not set -# CONFIG_INPUT_MOUSEDEV is not set -CONFIG_INPUT_EVDEV=y -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -CONFIG_INPUT_TOUCHSCREEN=y -# CONFIG_SERIO is not set -# CONFIG_CONSOLE_TRANSLATIONS is not set -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_NR_UARTS=1 -CONFIG_SERIAL_IMX=y -CONFIG_SERIAL_IMX_CONSOLE=y -# CONFIG_LEGACY_PTYS is not set -# CONFIG_HW_RANDOM is not set -CONFIG_I2C=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_IMX=y -CONFIG_SPI=y -# CONFIG_HWMON is not set -CONFIG_FB=y -CONFIG_FB_IMX=y -# CONFIG_VGA_CONSOLE is not set -CONFIG_FRAMEBUFFER_CONSOLE=y -CONFIG_FONTS=y -CONFIG_FONT_8x8=y -CONFIG_LOGO=y -# CONFIG_HID_SUPPORT is not set -# CONFIG_USB_SUPPORT is not set -CONFIG_MMC=y -CONFIG_MMC_MXC=y -# CONFIG_DNOTIFY is not set -CONFIG_MSDOS_FS=y -CONFIG_TMPFS=y -CONFIG_JFFS2_FS=y -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -CONFIG_ROOT_NFS=y -# CONFIG_RCU_CPU_STALL_DETECTOR is not set -CONFIG_SYSCTL_SYSCALL_CHECK=y -# CONFIG_CRYPTO_ANSI_CPRNG is not set diff --git a/arch/arm/configs/mx3_defconfig b/arch/arm/configs/mx3_defconfig index 7c4b30b34952ddb058df0621bcd73b940e5574db..cb0717fbb03d3a6eebad8d6cae49e69700b89041 100644 --- a/arch/arm/configs/mx3_defconfig +++ b/arch/arm/configs/mx3_defconfig @@ -3,7 +3,6 @@ CONFIG_SYSVIPC=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 -CONFIG_SYSFS_DEPRECATED_V2=y CONFIG_EXPERT=y CONFIG_SLAB=y CONFIG_MODULES=y @@ -13,20 +12,21 @@ CONFIG_MODVERSIONS=y # CONFIG_BLK_DEV_BSG is not set CONFIG_ARCH_MXC=y CONFIG_MACH_MX31ADS_WM1133_EV1=y +CONFIG_MACH_MX31LILLY=y +CONFIG_MACH_MX31LITE=y CONFIG_MACH_PCM037=y CONFIG_MACH_PCM037_EET=y -CONFIG_MACH_MX31LITE=y CONFIG_MACH_MX31_3DS=y CONFIG_MACH_MX31MOBOARD=y -CONFIG_MACH_MX31LILLY=y CONFIG_MACH_QONG=y -CONFIG_MACH_PCM043=y CONFIG_MACH_ARMADILLO5X0=y -CONFIG_MACH_MX35_3DS=y CONFIG_MACH_KZM_ARM11_01=y +CONFIG_MACH_PCM043=y +CONFIG_MACH_MX35_3DS=y CONFIG_MACH_EUKREA_CPUIMX35=y CONFIG_MXC_IRQ_PRIOR=y CONFIG_MXC_PWM=y +CONFIG_ARM_ERRATA_411920=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_PREEMPT=y @@ -35,7 +35,6 @@ CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/mtdblock2 rw ip=off" CONFIG_VFP=y -CONFIG_PM=y CONFIG_PM_DEBUG=y CONFIG_NET=y CONFIG_PACKET=y @@ -52,7 +51,6 @@ CONFIG_IP_PNP_DHCP=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_FW_LOADER=m CONFIG_MTD=y -CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y @@ -62,24 +60,27 @@ CONFIG_MTD_NAND=y CONFIG_MTD_NAND_MXC=y CONFIG_MTD_UBI=y # CONFIG_BLK_DEV is not set +CONFIG_MISC_DEVICES=y CONFIG_EEPROM_AT24=y CONFIG_NETDEVICES=y CONFIG_SMSC_PHY=y CONFIG_NET_ETHERNET=y CONFIG_SMSC911X=y CONFIG_DNET=y -CONFIG_FEC=y # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set -# CONFIG_INPUT is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_KEYBOARD_ATKBD is not set +CONFIG_KEYBOARD_IMX=y +# CONFIG_INPUT_MOUSE is not set # CONFIG_SERIO is not set # CONFIG_VT is not set +# CONFIG_LEGACY_PTYS is not set CONFIG_SERIAL_8250=m CONFIG_SERIAL_8250_EXTENDED=y CONFIG_SERIAL_8250_SHARE_IRQ=y CONFIG_SERIAL_IMX=y CONFIG_SERIAL_IMX_CONSOLE=y -# CONFIG_LEGACY_PTYS is not set # CONFIG_HW_RANDOM is not set CONFIG_I2C=y CONFIG_I2C_CHARDEV=y @@ -89,12 +90,15 @@ CONFIG_W1=y CONFIG_W1_MASTER_MXC=y CONFIG_W1_SLAVE_THERM=y # CONFIG_HWMON is not set +CONFIG_WATCHDOG=y +CONFIG_IMX2_WDT=y CONFIG_MFD_WM8350_I2C=y CONFIG_REGULATOR=y CONFIG_REGULATOR_WM8350=y CONFIG_MEDIA_SUPPORT=y CONFIG_VIDEO_DEV=y -# CONFIG_VIDEO_ALLOW_V4L1 is not set +# CONFIG_RC_CORE is not set +# CONFIG_MEDIA_TUNER_CUSTOMISE is not set CONFIG_SOC_CAMERA=y CONFIG_SOC_CAMERA_MT9M001=y CONFIG_SOC_CAMERA_MT9M111=y @@ -105,9 +109,26 @@ CONFIG_SOC_CAMERA_OV772X=y CONFIG_VIDEO_MX3=y # CONFIG_RADIO_ADAPTERS is not set CONFIG_FB=y -# CONFIG_USB_SUPPORT is not set +CONFIG_SOUND=y +CONFIG_SND=y +# CONFIG_SND_ARM is not set +# CONFIG_SND_SPI is not set +CONFIG_SND_SOC=y +CONFIG_SND_IMX_SOC=y +CONFIG_SND_MXC_SOC_WM1133_EV1=y +CONFIG_SND_SOC_PHYCORE_AC97=y +CONFIG_SND_SOC_EUKREA_TLV320=y +CONFIG_USB=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_MXC=y +CONFIG_USB_GADGET=m +CONFIG_USB_FSL_USB2=m +CONFIG_USB_G_SERIAL=m +CONFIG_USB_ULPI=y CONFIG_MMC=y CONFIG_MMC_MXC=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_MXC=y CONFIG_DMADEVICES=y # CONFIG_DNOTIFY is not set CONFIG_TMPFS=y @@ -119,6 +140,5 @@ CONFIG_NFS_V4=y CONFIG_ROOT_NFS=y # CONFIG_ENABLE_WARN_DEPRECATED is not set # CONFIG_ENABLE_MUST_CHECK is not set -# CONFIG_RCU_CPU_STALL_DETECTOR is not set CONFIG_SYSCTL_SYSCALL_CHECK=y # CONFIG_CRYPTO_ANSI_CPRNG is not set diff --git a/arch/arm/configs/mx51_defconfig b/arch/arm/configs/mx5_defconfig similarity index 82% rename from arch/arm/configs/mx51_defconfig rename to arch/arm/configs/mx5_defconfig index 88c5802a23514b06d0c2c6b4e07cdc35a502c32d..d0d8dfece37ee7073023b7ea3f1fade5ffebc1d0 100644 --- a/arch/arm/configs/mx51_defconfig +++ b/arch/arm/configs/mx5_defconfig @@ -1,5 +1,6 @@ CONFIG_EXPERIMENTAL=y # CONFIG_LOCALVERSION_AUTO is not set +CONFIG_KERNEL_LZO=y CONFIG_SYSVIPC=y CONFIG_LOG_BUF_SHIFT=18 CONFIG_RELAY=y @@ -13,21 +14,29 @@ CONFIG_MODULE_SRCVERSION_ALL=y # CONFIG_LBDAF is not set # CONFIG_BLK_DEV_BSG is not set CONFIG_ARCH_MXC=y -CONFIG_ARCH_MX51=y +CONFIG_ARCH_MX5=y CONFIG_MACH_MX51_BABBAGE=y CONFIG_MACH_MX51_3DS=y CONFIG_MACH_EUKREA_CPUIMX51=y +CONFIG_MACH_EUKREA_CPUIMX51SD=y +CONFIG_MACH_MX51_EFIKAMX=y +CONFIG_MACH_MX51_EFIKASB=y +CONFIG_MACH_MX53_EVK=y +CONFIG_MACH_MX53_SMD=y +CONFIG_MACH_MX53_LOCO=y +CONFIG_MACH_MX53_ARD=y +CONFIG_MXC_PWM=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y +CONFIG_VMSPLIT_2G=y CONFIG_PREEMPT_VOLUNTARY=y CONFIG_AEABI=y # CONFIG_OABI_COMPAT is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 -CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.0.101:/shared/nfs ip=dhcp" +CONFIG_CMDLINE="noinitrd console=ttymxc0,115200" CONFIG_VFP=y CONFIG_NEON=y CONFIG_BINFMT_MISC=m -CONFIG_PM=y CONFIG_PM_DEBUG=y CONFIG_PM_TEST_SUSPEND=y CONFIG_NET=y @@ -42,13 +51,13 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_INET_LRO is not set # CONFIG_IPV6 is not set # CONFIG_WIRELESS is not set +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y # CONFIG_STANDALONE is not set CONFIG_CONNECTOR=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=65536 -# CONFIG_MISC_DEVICES is not set -CONFIG_SCSI=y # CONFIG_SCSI_PROC_FS is not set CONFIG_BLK_DEV_SD=y CONFIG_SCSI_MULTI_LUN=y @@ -56,8 +65,10 @@ CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y CONFIG_SCSI_SCAN_ASYNC=y # CONFIG_SCSI_LOWLEVEL is not set -CONFIG_ATA=m +CONFIG_ATA=y +CONFIG_PATA_IMX=y CONFIG_NETDEVICES=y +CONFIG_MII=m CONFIG_MARVELL_PHY=y CONFIG_DAVICOM_PHY=y CONFIG_QSEMI_PHY=y @@ -71,49 +82,57 @@ CONFIG_REALTEK_PHY=y CONFIG_NATIONAL_PHY=y CONFIG_STE10XP=y CONFIG_LSI_ET1011C_PHY=y -CONFIG_MDIO_BITBANG=y -CONFIG_MDIO_GPIO=y +CONFIG_MICREL_PHY=y CONFIG_NET_ETHERNET=y -CONFIG_MII=m -CONFIG_FEC=y # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set # CONFIG_WLAN is not set -CONFIG_INPUT_FF_MEMLESS=m # CONFIG_INPUT_MOUSEDEV_PSAUX is not set CONFIG_INPUT_EVDEV=y -CONFIG_KEYBOARD_GPIO=y CONFIG_INPUT_EVBUG=m +CONFIG_KEYBOARD_GPIO=y CONFIG_MOUSE_PS2=m CONFIG_MOUSE_PS2_ELANTECH=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_MMA8450=y CONFIG_SERIO_SERPORT=m CONFIG_VT_HW_CONSOLE_BINDING=y +# CONFIG_LEGACY_PTYS is not set # CONFIG_DEVKMEM is not set CONFIG_SERIAL_IMX=y CONFIG_SERIAL_IMX_CONSOLE=y -# CONFIG_LEGACY_PTYS is not set CONFIG_HW_RANDOM=y CONFIG_I2C=y # CONFIG_I2C_COMPAT is not set -CONFIG_I2C_CHARDEV=m +CONFIG_I2C_CHARDEV=y # CONFIG_I2C_HELPER_AUTO is not set CONFIG_I2C_ALGOBIT=m CONFIG_I2C_ALGOPCF=m CONFIG_I2C_ALGOPCA=m +CONFIG_I2C_IMX=y +CONFIG_SPI=y +CONFIG_SPI_IMX=y CONFIG_GPIO_SYSFS=y # CONFIG_HWMON is not set -# CONFIG_HID_SUPPORT is not set +CONFIG_WATCHDOG=y +CONFIG_IMX2_WDT=y +CONFIG_MFD_MC13XXX=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_MC13892=y CONFIG_USB=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_MXC=y CONFIG_USB_STORAGE=y CONFIG_MMC=y CONFIG_MMC_BLOCK=m -CONFIG_MMC_SDHCI=m +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_ESDHC_IMX=y CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y CONFIG_RTC_CLASS=y CONFIG_RTC_INTF_DEV_UIE_EMUL=y +CONFIG_RTC_MXC=y CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y @@ -127,7 +146,6 @@ CONFIG_EXT4_FS_SECURITY=y CONFIG_QUOTA=y CONFIG_QUOTA_NETLINK_INTERFACE=y # CONFIG_PRINT_QUOTA_WARNING is not set -CONFIG_AUTOFS_FS=y CONFIG_AUTOFS4_FS=y CONFIG_FUSE_FS=y CONFIG_ISO9660_FS=m @@ -151,17 +169,13 @@ CONFIG_NLS_ISO8859_15=m CONFIG_NLS_UTF8=y CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_FS=y -CONFIG_DEBUG_KERNEL=y # CONFIG_SCHED_DEBUG is not set # CONFIG_DEBUG_BUGVERBOSE is not set -# CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_FTRACE is not set # CONFIG_ARM_UNWIND is not set -CONFIG_DEBUG_LL=y -CONFIG_EARLY_PRINTK=y CONFIG_SECURITYFS=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_LZO=m # CONFIG_CRYPTO_ANSI_CPRNG is not set # CONFIG_CRYPTO_HW is not set CONFIG_CRC_CCITT=m diff --git a/arch/arm/configs/mxs_defconfig b/arch/arm/configs/mxs_defconfig index db2cb7d180dc0283602744964f27798e778314eb..6ee781bf6bf131ceeebac6900d69ae41774dac62 100644 --- a/arch/arm/configs/mxs_defconfig +++ b/arch/arm/configs/mxs_defconfig @@ -26,6 +26,7 @@ CONFIG_MACH_MX23EVK=y CONFIG_MACH_MX28EVK=y CONFIG_MACH_STMP378X_DEVB=y CONFIG_MACH_TX28=y +CONFIG_MACH_M28EVK=y # CONFIG_ARM_THUMB is not set CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig index 8845f1c9925d9809749c3740cff3a6c1c02f9180..195729760aeb036bd35f817f3f3eed657055320f 100644 --- a/arch/arm/configs/tegra_defconfig +++ b/arch/arm/configs/tegra_defconfig @@ -25,6 +25,7 @@ CONFIG_MACH_KAEN=y CONFIG_MACH_PAZ00=y CONFIG_MACH_TRIMSLICE=y CONFIG_MACH_WARIO=y +CONFIG_MACH_VENTANA=y CONFIG_TEGRA_DEBUG_UARTD=y CONFIG_ARM_ERRATA_742230=y CONFIG_NO_HZ=y @@ -38,7 +39,6 @@ CONFIG_HIGHMEM=y CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_VFP=y -CONFIG_PM=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y @@ -65,6 +65,7 @@ CONFIG_IPV6_TUNNEL=y CONFIG_IPV6_MULTIPLE_TABLES=y # CONFIG_WIRELESS is not set # CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_PROC_DEVICETREE=y CONFIG_BLK_DEV_LOOP=y CONFIG_MISC_DEVICES=y CONFIG_AD525X_DPOT=y @@ -72,34 +73,61 @@ CONFIG_AD525X_DPOT_I2C=y CONFIG_ICS932S401=y CONFIG_APDS9802ALS=y CONFIG_ISL29003=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +# CONFIG_SCSI_LOWLEVEL is not set CONFIG_NETDEVICES=y CONFIG_DUMMY=y +CONFIG_NET_ETHERNET=y CONFIG_R8169=y # CONFIG_NETDEV_10000 is not set # CONFIG_WLAN is not set +CONFIG_USB_PEGASUS=y +CONFIG_USB_USBNET=y +CONFIG_USB_NET_SMSC75XX=y +CONFIG_USB_NET_SMSC95XX=y # CONFIG_INPUT is not set # CONFIG_SERIO is not set # CONFIG_VT is not set +# CONFIG_LEGACY_PTYS is not set # CONFIG_DEVKMEM is not set CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_LEGACY_PTYS is not set +CONFIG_SERIAL_OF_PLATFORM=y # CONFIG_HW_RANDOM is not set CONFIG_I2C=y # CONFIG_I2C_COMPAT is not set # CONFIG_I2C_HELPER_AUTO is not set CONFIG_I2C_TEGRA=y +CONFIG_SPI=y +CONFIG_SPI_TEGRA=y CONFIG_SENSORS_LM90=y CONFIG_MFD_TPS6586X=y CONFIG_REGULATOR=y CONFIG_REGULATOR_TPS6586X=y -# CONFIG_USB_SUPPORT is not set +CONFIG_SOUND=y +CONFIG_SND=y +# CONFIG_SND_SUPPORT_OLD_API is not set +# CONFIG_SND_DRIVERS is not set +# CONFIG_SND_PCI is not set +# CONFIG_SND_ARM is not set +# CONFIG_SND_SPI is not set +# CONFIG_SND_USB is not set +CONFIG_SND_SOC=y +CONFIG_SND_SOC_TEGRA=y +CONFIG_SND_SOC_TEGRA_WM8903=y +CONFIG_SND_SOC_TEGRA_TRIMSLICE=y +CONFIG_USB=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_TEGRA=y +CONFIG_USB_STORAGE=y CONFIG_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_SDHCI_TEGRA=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_TEGRA=y CONFIG_STAGING=y -# CONFIG_STAGING_EXCLUDE_BUILD is not set CONFIG_IIO=y CONFIG_SENSORS_ISL29018=y CONFIG_SENSORS_AK8975=y @@ -123,18 +151,15 @@ CONFIG_NLS_ISO8859_1=y CONFIG_PRINTK_TIME=y CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_FS=y -CONFIG_DEBUG_KERNEL=y CONFIG_DETECT_HUNG_TASK=y CONFIG_SCHEDSTATS=y CONFIG_TIMER_STATS=y CONFIG_DEBUG_SLAB=y # CONFIG_DEBUG_PREEMPT is not set CONFIG_DEBUG_MUTEXES=y -CONFIG_DEBUG_SPINLOCK_SLEEP=y CONFIG_DEBUG_INFO=y CONFIG_DEBUG_VM=y CONFIG_DEBUG_SG=y -# CONFIG_RCU_CPU_STALL_DETECTOR is not set CONFIG_DEBUG_LL=y CONFIG_EARLY_PRINTK=y CONFIG_CRYPTO_ECB=y diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild index 6550db3aa5c7d41351e29e9f8a72a0a927a07cfa..960abceb8e14dd878fd7b5cf979a3c318021f0f4 100644 --- a/arch/arm/include/asm/Kbuild +++ b/arch/arm/include/asm/Kbuild @@ -1,3 +1,20 @@ include include/asm-generic/Kbuild.asm header-y += hwcap.h + +generic-y += auxvec.h +generic-y += bitsperlong.h +generic-y += cputime.h +generic-y += emergency-restart.h +generic-y += errno.h +generic-y += ioctl.h +generic-y += irq_regs.h +generic-y += kdebug.h +generic-y += local.h +generic-y += local64.h +generic-y += percpu.h +generic-y += poll.h +generic-y += resource.h +generic-y += sections.h +generic-y += siginfo.h +generic-y += sizes.h diff --git a/arch/arm/include/asm/auxvec.h b/arch/arm/include/asm/auxvec.h deleted file mode 100644 index c0536f6b29a74665ca2774dc99b970c8d0818fe5..0000000000000000000000000000000000000000 --- a/arch/arm/include/asm/auxvec.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef __ASMARM_AUXVEC_H -#define __ASMARM_AUXVEC_H - -#endif diff --git a/arch/arm/include/asm/bitsperlong.h b/arch/arm/include/asm/bitsperlong.h deleted file mode 100644 index 6dc0bb0c13b29dd814f403f2fd4efb3b36be0619..0000000000000000000000000000000000000000 --- a/arch/arm/include/asm/bitsperlong.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/arm/include/asm/bug.h b/arch/arm/include/asm/bug.h index 4d88425a41693e3778a62250bf09eac6446b1d3d..9abe7a07d5acdde3eea377cda3634e5f5c838115 100644 --- a/arch/arm/include/asm/bug.h +++ b/arch/arm/include/asm/bug.h @@ -3,21 +3,58 @@ #ifdef CONFIG_BUG -#ifdef CONFIG_DEBUG_BUGVERBOSE -extern void __bug(const char *file, int line) __attribute__((noreturn)); - -/* give file/line information */ -#define BUG() __bug(__FILE__, __LINE__) +/* + * Use a suitable undefined instruction to use for ARM/Thumb2 bug handling. + * We need to be careful not to conflict with those used by other modules and + * the register_undef_hook() system. + */ +#ifdef CONFIG_THUMB2_KERNEL +#define BUG_INSTR_VALUE 0xde02 +#define BUG_INSTR_TYPE ".hword " #else +#define BUG_INSTR_VALUE 0xe7f001f2 +#define BUG_INSTR_TYPE ".word " +#endif -/* this just causes an oops */ -#define BUG() do { *(int *)0 = 0; } while (1) -#endif +#define BUG() _BUG(__FILE__, __LINE__, BUG_INSTR_VALUE) +#define _BUG(file, line, value) __BUG(file, line, value) + +#ifdef CONFIG_DEBUG_BUGVERBOSE + +/* + * The extra indirection is to ensure that the __FILE__ string comes through + * OK. Many version of gcc do not support the asm %c parameter which would be + * preferable to this unpleasantness. We use mergeable string sections to + * avoid multiple copies of the string appearing in the kernel image. + */ + +#define __BUG(__file, __line, __value) \ +do { \ + BUILD_BUG_ON(sizeof(struct bug_entry) != 12); \ + asm volatile("1:\t" BUG_INSTR_TYPE #__value "\n" \ + ".pushsection .rodata.str, \"aMS\", %progbits, 1\n" \ + "2:\t.asciz " #__file "\n" \ + ".popsection\n" \ + ".pushsection __bug_table,\"a\"\n" \ + "3:\t.word 1b, 2b\n" \ + "\t.hword " #__line ", 0\n" \ + ".popsection"); \ + unreachable(); \ +} while (0) + +#else /* not CONFIG_DEBUG_BUGVERBOSE */ + +#define __BUG(__file, __line, __value) \ +do { \ + asm volatile(BUG_INSTR_TYPE #__value); \ + unreachable(); \ +} while (0) +#endif /* CONFIG_DEBUG_BUGVERBOSE */ #define HAVE_ARCH_BUG -#endif +#endif /* CONFIG_BUG */ #include diff --git a/arch/arm/include/asm/cachetype.h b/arch/arm/include/asm/cachetype.h index c023db09fcc14ced27ec4bacaca40b44c48005ad..7ea78144ae22ec61ae7623b07c9d22f08ef69e87 100644 --- a/arch/arm/include/asm/cachetype.h +++ b/arch/arm/include/asm/cachetype.h @@ -7,6 +7,7 @@ #define CACHEID_VIPT (CACHEID_VIPT_ALIASING|CACHEID_VIPT_NONALIASING) #define CACHEID_ASID_TAGGED (1 << 3) #define CACHEID_VIPT_I_ALIASING (1 << 4) +#define CACHEID_PIPT (1 << 5) extern unsigned int cacheid; @@ -16,6 +17,7 @@ extern unsigned int cacheid; #define cache_is_vipt_aliasing() cacheid_is(CACHEID_VIPT_ALIASING) #define icache_is_vivt_asid_tagged() cacheid_is(CACHEID_ASID_TAGGED) #define icache_is_vipt_aliasing() cacheid_is(CACHEID_VIPT_I_ALIASING) +#define icache_is_pipt() cacheid_is(CACHEID_PIPT) /* * __LINUX_ARM_ARCH__ is the minimum supported CPU architecture @@ -26,7 +28,8 @@ extern unsigned int cacheid; #if __LINUX_ARM_ARCH__ >= 7 #define __CACHEID_ARCH_MIN (CACHEID_VIPT_NONALIASING |\ CACHEID_ASID_TAGGED |\ - CACHEID_VIPT_I_ALIASING) + CACHEID_VIPT_I_ALIASING |\ + CACHEID_PIPT) #elif __LINUX_ARM_ARCH__ >= 6 #define __CACHEID_ARCH_MIN (~CACHEID_VIVT) #else diff --git a/arch/arm/include/asm/cputime.h b/arch/arm/include/asm/cputime.h deleted file mode 100644 index 3a8002a5fec7232e1c9cd74dbab920f2ab443d50..0000000000000000000000000000000000000000 --- a/arch/arm/include/asm/cputime.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ARM_CPUTIME_H -#define __ARM_CPUTIME_H - -#include - -#endif /* __ARM_CPUTIME_H */ diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h index cd4458f64171e5e40720b991e8df5ad72099b0c5..cb47d28cbe1f81c4cfb43de4d1f08dbcec9f0cf7 100644 --- a/arch/arm/include/asm/cputype.h +++ b/arch/arm/include/asm/cputype.h @@ -8,6 +8,7 @@ #define CPUID_CACHETYPE 1 #define CPUID_TCM 2 #define CPUID_TLBTYPE 3 +#define CPUID_MPIDR 5 #define CPUID_EXT_PFR0 "c1, 0" #define CPUID_EXT_PFR1 "c1, 1" @@ -70,6 +71,11 @@ static inline unsigned int __attribute_const__ read_cpuid_tcmstatus(void) return read_cpuid(CPUID_TCM); } +static inline unsigned int __attribute_const__ read_cpuid_mpidr(void) +{ + return read_cpuid(CPUID_MPIDR); +} + /* * Intel's XScale3 core supports some v6 features (supersections, L2) * but advertises itself as v5 as it does not support the v6 ISA. For diff --git a/arch/arm/include/asm/device.h b/arch/arm/include/asm/device.h index 9f390ce335cb00743cb6cd717819f0750b63b0db..7aa368003b05220cc1f0ba9301a15e5699db2278 100644 --- a/arch/arm/include/asm/device.h +++ b/arch/arm/include/asm/device.h @@ -10,9 +10,17 @@ struct dev_archdata { #ifdef CONFIG_DMABOUNCE struct dmabounce_device_info *dmabounce; #endif +#ifdef CONFIG_IOMMU_API + void *iommu; /* private IOMMU data */ +#endif }; +struct omap_device; + struct pdev_archdata { +#ifdef CONFIG_ARCH_OMAP + struct omap_device *od; +#endif }; #endif diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index 7a21d0bf7134d2ec16b8afeb87ea1c184ee2f717..cb3b7c981c4b729c31c8dbf33c9fa4334edfc07d 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h @@ -32,7 +32,7 @@ static inline unsigned long dma_to_pfn(struct device *dev, dma_addr_t addr) static inline void *dma_to_virt(struct device *dev, dma_addr_t addr) { - return (void *)__bus_to_virt(addr); + return (void *)__bus_to_virt((unsigned long)addr); } static inline dma_addr_t virt_to_dma(struct device *dev, void *addr) @@ -205,6 +205,13 @@ extern void *dma_alloc_writecombine(struct device *, size_t, dma_addr_t *, int dma_mmap_writecombine(struct device *, struct vm_area_struct *, void *, dma_addr_t, size_t); +/* + * This can be called during boot to increase the size of the consistent + * DMA region above it's default value of 2MB. It must be called before the + * memory allocator is initialised, i.e. before any core_initcall. + */ +extern void __init init_consistent_dma_size(unsigned long size); + #ifdef CONFIG_DMABOUNCE /* diff --git a/arch/arm/include/asm/dma.h b/arch/arm/include/asm/dma.h index 628670e9d7c95b34d23230448ca09358944b0998..69a5b0b6455c72af47fe8df6db36e310cc97b8f2 100644 --- a/arch/arm/include/asm/dma.h +++ b/arch/arm/include/asm/dma.h @@ -34,18 +34,18 @@ #define DMA_MODE_CASCADE 0xc0 #define DMA_AUTOINIT 0x10 -extern spinlock_t dma_spin_lock; +extern raw_spinlock_t dma_spin_lock; static inline unsigned long claim_dma_lock(void) { unsigned long flags; - spin_lock_irqsave(&dma_spin_lock, flags); + raw_spin_lock_irqsave(&dma_spin_lock, flags); return flags; } static inline void release_dma_lock(unsigned long flags) { - spin_unlock_irqrestore(&dma_spin_lock, flags); + raw_spin_unlock_irqrestore(&dma_spin_lock, flags); } /* Clear the 'DMA Pointer Flip Flop'. diff --git a/arch/arm/include/asm/ecard.h b/arch/arm/include/asm/ecard.h index 29f2610efc70775a7059f4b5f63e1cc175c78749..eaea14676d5732798433ad91cb25f05482b75147 100644 --- a/arch/arm/include/asm/ecard.h +++ b/arch/arm/include/asm/ecard.h @@ -161,7 +161,6 @@ struct expansion_card { /* Private internal data */ const char *card_desc; /* Card description */ - CONST unsigned int podaddr; /* Base Linux address for card */ CONST loader_t loader; /* loader program */ u64 dma_mask; }; diff --git a/arch/arm/include/asm/emergency-restart.h b/arch/arm/include/asm/emergency-restart.h deleted file mode 100644 index 108d8c48e42e86978077354f2fa1b151f25c41df..0000000000000000000000000000000000000000 --- a/arch/arm/include/asm/emergency-restart.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_EMERGENCY_RESTART_H -#define _ASM_EMERGENCY_RESTART_H - -#include - -#endif /* _ASM_EMERGENCY_RESTART_H */ diff --git a/arch/arm/include/asm/entry-macro-multi.S b/arch/arm/include/asm/entry-macro-multi.S index 2f1e2098dfe778211e9209ea0285e089020e5745..88d61815f0c03caceaa94af319687b6dbd6913ce 100644 --- a/arch/arm/include/asm/entry-macro-multi.S +++ b/arch/arm/include/asm/entry-macro-multi.S @@ -25,13 +25,6 @@ movne r1, sp adrne lr, BSYM(1b) bne do_IPI - -#ifdef CONFIG_LOCAL_TIMERS - test_for_ltirq r0, r2, r6, lr - movne r0, sp - adrne lr, BSYM(1b) - bne do_local_timer -#endif #endif 9997: .endm diff --git a/arch/arm/include/asm/errno.h b/arch/arm/include/asm/errno.h deleted file mode 100644 index 6e60f0612bb64b61c65f166ce08e2f363e041fb0..0000000000000000000000000000000000000000 --- a/arch/arm/include/asm/errno.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ARM_ERRNO_H -#define _ARM_ERRNO_H - -#include - -#endif diff --git a/arch/arm/include/asm/exception.h b/arch/arm/include/asm/exception.h new file mode 100644 index 0000000000000000000000000000000000000000..5abaf5bbd985f1049c65e6368c3e868399bb609e --- /dev/null +++ b/arch/arm/include/asm/exception.h @@ -0,0 +1,19 @@ +/* + * Annotations for marking C functions as exception handlers. + * + * These should only be used for C functions that are called from the low + * level exception entry code and not any intervening C code. + */ +#ifndef __ASM_ARM_EXCEPTION_H +#define __ASM_ARM_EXCEPTION_H + +#include + +#define __exception __attribute__((section(".exception.text"))) +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +#define __exception_irq_entry __irq_entry +#else +#define __exception_irq_entry __exception +#endif + +#endif /* __ASM_ARM_EXCEPTION_H */ diff --git a/arch/arm/include/asm/gpio.h b/arch/arm/include/asm/gpio.h index 166a7a3e28400db64062715a53bdb2f31d4e9df4..11ad0bfbb0ad67ca3c3865d25a216b22a13c10f5 100644 --- a/arch/arm/include/asm/gpio.h +++ b/arch/arm/include/asm/gpio.h @@ -4,4 +4,23 @@ /* not all ARM platforms necessarily support this API ... */ #include +#ifndef __ARM_GPIOLIB_COMPLEX +/* Note: this may rely upon the value of ARCH_NR_GPIOS set in mach/gpio.h */ +#include + +/* The trivial gpiolib dispatchers */ +#define gpio_get_value __gpio_get_value +#define gpio_set_value __gpio_set_value +#define gpio_cansleep __gpio_cansleep +#endif + +/* + * Provide a default gpio_to_irq() which should satisfy every case. + * However, some platforms want to do this differently, so allow them + * to override it. + */ +#ifndef gpio_to_irq +#define gpio_to_irq __gpio_to_irq +#endif + #endif /* _ARCH_ARM_GPIO_H */ diff --git a/arch/arm/include/asm/hardirq.h b/arch/arm/include/asm/hardirq.h index 89ad1805e5797625a2d5df0912253bcd9e2a9f5f..ddf07a92a6c8484029927aa51fa09816ce38c337 100644 --- a/arch/arm/include/asm/hardirq.h +++ b/arch/arm/include/asm/hardirq.h @@ -9,9 +9,6 @@ typedef struct { unsigned int __softirq_pending; -#ifdef CONFIG_LOCAL_TIMERS - unsigned int local_timer_irqs; -#endif #ifdef CONFIG_SMP unsigned int ipi_irqs[NR_IPI]; #endif diff --git a/arch/arm/include/asm/hardware/cache-l2x0.h b/arch/arm/include/asm/hardware/cache-l2x0.h index 99a6ed7e1bfd5ce6395ca7a900079ada255da281..1db1143a94838cb92419040c40009f17d1ee2f97 100644 --- a/arch/arm/include/asm/hardware/cache-l2x0.h +++ b/arch/arm/include/asm/hardware/cache-l2x0.h @@ -52,6 +52,8 @@ #define L2X0_LOCKDOWN_WAY_D_BASE 0x900 #define L2X0_LOCKDOWN_WAY_I_BASE 0x904 #define L2X0_LOCKDOWN_STRIDE 0x08 +#define L2X0_ADDR_FILTER_START 0xC00 +#define L2X0_ADDR_FILTER_END 0xC04 #define L2X0_TEST_OPERATION 0xF00 #define L2X0_LINE_DATA 0xF10 #define L2X0_LINE_TAG 0xF30 @@ -65,8 +67,23 @@ #define L2X0_CACHE_ID_PART_MASK (0xf << 6) #define L2X0_CACHE_ID_PART_L210 (1 << 6) #define L2X0_CACHE_ID_PART_L310 (3 << 6) +#define L2X0_CACHE_ID_RTL_MASK 0x3f +#define L2X0_CACHE_ID_RTL_R0P0 0x0 +#define L2X0_CACHE_ID_RTL_R1P0 0x2 +#define L2X0_CACHE_ID_RTL_R2P0 0x4 +#define L2X0_CACHE_ID_RTL_R3P0 0x5 +#define L2X0_CACHE_ID_RTL_R3P1 0x6 +#define L2X0_CACHE_ID_RTL_R3P2 0x8 #define L2X0_AUX_CTRL_MASK 0xc0000fff +#define L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT 0 +#define L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK 0x7 +#define L2X0_AUX_CTRL_DATA_WR_LATENCY_SHIFT 3 +#define L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK (0x7 << 3) +#define L2X0_AUX_CTRL_TAG_LATENCY_SHIFT 6 +#define L2X0_AUX_CTRL_TAG_LATENCY_MASK (0x7 << 6) +#define L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT 9 +#define L2X0_AUX_CTRL_DIRTY_LATENCY_MASK (0x7 << 9) #define L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT 16 #define L2X0_AUX_CTRL_WAY_SIZE_SHIFT 17 #define L2X0_AUX_CTRL_WAY_SIZE_MASK (0x7 << 17) @@ -77,8 +94,40 @@ #define L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT 29 #define L2X0_AUX_CTRL_EARLY_BRESP_SHIFT 30 +#define L2X0_LATENCY_CTRL_SETUP_SHIFT 0 +#define L2X0_LATENCY_CTRL_RD_SHIFT 4 +#define L2X0_LATENCY_CTRL_WR_SHIFT 8 + +#define L2X0_ADDR_FILTER_EN 1 + #ifndef __ASSEMBLY__ extern void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask); +#if defined(CONFIG_CACHE_L2X0) && defined(CONFIG_OF) +extern int l2x0_of_init(__u32 aux_val, __u32 aux_mask); +#else +static inline int l2x0_of_init(__u32 aux_val, __u32 aux_mask) +{ + return -ENODEV; +} #endif +struct l2x0_regs { + unsigned long phy_base; + unsigned long aux_ctrl; + /* + * Whether the following registers need to be saved/restored + * depends on platform + */ + unsigned long tag_latency; + unsigned long data_latency; + unsigned long filter_start; + unsigned long filter_end; + unsigned long prefetch_ctrl; + unsigned long pwr_ctrl; +}; + +extern struct l2x0_regs l2x0_saved_regs; + +#endif /* __ASSEMBLY__ */ + #endif diff --git a/arch/arm/include/asm/hardware/entry-macro-gic.S b/arch/arm/include/asm/hardware/entry-macro-gic.S index c115b82fe80a4ce8807b0de04b9c53d647c9aa12..74ebc803904d7cd9df4b348c895ac3787a27d410 100644 --- a/arch/arm/include/asm/hardware/entry-macro-gic.S +++ b/arch/arm/include/asm/hardware/entry-macro-gic.S @@ -22,15 +22,11 @@ * interrupt controller spec. To wit: * * Interrupts 0-15 are IPI - * 16-28 are reserved - * 29-31 are local. We allow 30 to be used for the watchdog. + * 16-31 are local. We allow 30 to be used for the watchdog. * 32-1020 are global * 1021-1022 are reserved * 1023 is "spurious" (no interrupt) * - * For now, we ignore all local interrupts so only return an interrupt if it's - * between 30 and 1020. The test_for_ipi routine below will pick up on IPIs. - * * A simple read from the controller will tell us the number of the highest * priority enabled interrupt. We then just need to check whether it is in the * valid range for an IRQ (30-1020 inclusive). @@ -43,7 +39,7 @@ ldr \tmp, =1021 bic \irqnr, \irqstat, #0x1c00 - cmp \irqnr, #29 + cmp \irqnr, #15 cmpcc \irqnr, \irqnr cmpne \irqnr, \tmp cmpcs \irqnr, \irqnr @@ -62,14 +58,3 @@ strcc \irqstat, [\base, #GIC_CPU_EOI] cmpcs \irqnr, \irqnr .endm - -/* As above, this assumes that irqstat and base are preserved.. */ - - .macro test_for_ltirq, irqnr, irqstat, base, tmp - bic \irqnr, \irqstat, #0x1c00 - mov \tmp, #0 - cmp \irqnr, #29 - moveq \tmp, #1 - streq \irqstat, [\base, #GIC_CPU_EOI] - cmp \tmp, #0 - .endm diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h index 435d3f86c708778c9ad8211451a1a1c2b75372fe..3e91f22046f55d602550c1a0961312f2c9d4ba33 100644 --- a/arch/arm/include/asm/hardware/gic.h +++ b/arch/arm/include/asm/hardware/gic.h @@ -33,19 +33,32 @@ #define GIC_DIST_SOFTINT 0xf00 #ifndef __ASSEMBLY__ +#include +struct device_node; + extern void __iomem *gic_cpu_base_addr; extern struct irq_chip gic_arch_extn; -void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *); +void gic_init(unsigned int, int, void __iomem *, void __iomem *); +int gic_of_init(struct device_node *node, struct device_node *parent); void gic_secondary_init(unsigned int); void gic_cascade_irq(unsigned int gic_nr, unsigned int irq); void gic_raise_softirq(const struct cpumask *mask, unsigned int irq); -void gic_enable_ppi(unsigned int); struct gic_chip_data { - unsigned int irq_offset; void __iomem *dist_base; void __iomem *cpu_base; +#ifdef CONFIG_CPU_PM + u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)]; + u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)]; + u32 saved_spi_target[DIV_ROUND_UP(1020, 4)]; + u32 __percpu *saved_ppi_enable; + u32 __percpu *saved_ppi_conf; +#endif +#ifdef CONFIG_IRQ_DOMAIN + struct irq_domain domain; +#endif + unsigned int gic_irqs; }; #endif diff --git a/arch/arm/include/asm/hardware/iop3xx-gpio.h b/arch/arm/include/asm/hardware/iop3xx-gpio.h index b69d972b1f7d21987c2ca86c7119cb101767f75d..9eda7dc92ad8d79c2214ac1ba472fa9e29c2357f 100644 --- a/arch/arm/include/asm/hardware/iop3xx-gpio.h +++ b/arch/arm/include/asm/hardware/iop3xx-gpio.h @@ -28,6 +28,8 @@ #include #include +#define __ARM_GPIOLIB_COMPLEX + #define IOP3XX_N_GPIOS 8 static inline int gpio_get_value(unsigned gpio) diff --git a/arch/arm/include/asm/hardware/it8152.h b/arch/arm/include/asm/hardware/it8152.h index b3fea38d55c6ca49d145d8e4723183707629c9a8..43cab498bc279c1e6f6078c03717e1c497384680 100644 --- a/arch/arm/include/asm/hardware/it8152.h +++ b/arch/arm/include/asm/hardware/it8152.h @@ -9,7 +9,7 @@ #ifndef __ASM_HARDWARE_IT8152_H #define __ASM_HARDWARE_IT8152_H -extern unsigned long it8152_base_address; +extern void __iomem *it8152_base_address; #define IT8152_IO_BASE (it8152_base_address + 0x03e00000) #define IT8152_CFGREG_BASE (it8152_base_address + 0x03f00000) diff --git a/arch/arm/include/asm/hw_breakpoint.h b/arch/arm/include/asm/hw_breakpoint.h index f389b2704d82110226254551e873d18f6c93a69c..c190bc992f0e6e917d2071c920312c7391beb5e3 100644 --- a/arch/arm/include/asm/hw_breakpoint.h +++ b/arch/arm/include/asm/hw_breakpoint.h @@ -50,6 +50,7 @@ static inline void decode_ctrl_reg(u32 reg, #define ARM_DEBUG_ARCH_V6_1 2 #define ARM_DEBUG_ARCH_V7_ECP14 3 #define ARM_DEBUG_ARCH_V7_MM 4 +#define ARM_DEBUG_ARCH_V7_1 5 /* Breakpoint */ #define ARM_BREAKPOINT_EXECUTE 0 @@ -57,6 +58,7 @@ static inline void decode_ctrl_reg(u32 reg, /* Watchpoints */ #define ARM_BREAKPOINT_LOAD 1 #define ARM_BREAKPOINT_STORE 2 +#define ARM_FSR_ACCESS_MASK (1 << 11) /* Privilege Levels */ #define ARM_BREAKPOINT_PRIV 1 diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index d66605dea55a217fc10df9fda8a94f3e5b1eb9ea..065d100fa63e7d608f49d3ef7f3a629d86cfe057 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -80,6 +80,7 @@ extern void __iomem *__arm_ioremap_caller(unsigned long, size_t, unsigned int, extern void __iomem *__arm_ioremap_pfn(unsigned long, unsigned long, size_t, unsigned int); extern void __iomem *__arm_ioremap(unsigned long, size_t, unsigned int); +extern void __iomem *__arm_ioremap_exec(unsigned long, size_t, bool cached); extern void __iounmap(volatile void __iomem *addr); /* @@ -109,6 +110,27 @@ static inline void __iomem *__typesafe_io(unsigned long addr) */ #include +/* + * This is the limit of PC card/PCI/ISA IO space, which is by default + * 64K if we have PC card, PCI or ISA support. Otherwise, default to + * zero to prevent ISA/PCI drivers claiming IO space (and potentially + * oopsing.) + * + * Only set this larger if you really need inb() et.al. to operate over + * a larger address space. Note that SOC_COMMON ioremaps each sockets + * IO space area, and so inb() et.al. must be defined to operate as per + * readb() et.al. on such platforms. + */ +#ifndef IO_SPACE_LIMIT +#if defined(CONFIG_PCMCIA_SOC_COMMON) || defined(CONFIG_PCMCIA_SOC_COMMON_MODULE) +#define IO_SPACE_LIMIT ((resource_size_t)0xffffffff) +#elif defined(CONFIG_PCI) || defined(CONFIG_ISA) || defined(CONFIG_PCCARD) +#define IO_SPACE_LIMIT ((resource_size_t)0xffff) +#else +#define IO_SPACE_LIMIT ((resource_size_t)0) +#endif +#endif + /* * IO port access primitives * ------------------------- @@ -189,11 +211,11 @@ extern void _memset_io(volatile void __iomem *, int, size_t); * IO port primitives for more information. */ #ifdef __mem_pci -#define readb_relaxed(c) ({ u8 __v = __raw_readb(__mem_pci(c)); __v; }) -#define readw_relaxed(c) ({ u16 __v = le16_to_cpu((__force __le16) \ - __raw_readw(__mem_pci(c))); __v; }) -#define readl_relaxed(c) ({ u32 __v = le32_to_cpu((__force __le32) \ - __raw_readl(__mem_pci(c))); __v; }) +#define readb_relaxed(c) ({ u8 __r = __raw_readb(__mem_pci(c)); __r; }) +#define readw_relaxed(c) ({ u16 __r = le16_to_cpu((__force __le16) \ + __raw_readw(__mem_pci(c))); __r; }) +#define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \ + __raw_readl(__mem_pci(c))); __r; }) #define writeb_relaxed(v,c) ((void)__raw_writeb(v,__mem_pci(c))) #define writew_relaxed(v,c) ((void)__raw_writew((__force u16) \ @@ -238,7 +260,7 @@ extern void _memset_io(volatile void __iomem *, int, size_t); * ioremap and friends. * * ioremap takes a PCI memory address, as specified in - * Documentation/IO-mapping.txt. + * Documentation/io-mapping.txt. * */ #ifndef __arch_ioremap @@ -260,10 +282,16 @@ extern void _memset_io(volatile void __iomem *, int, size_t); #define ioread16(p) ({ unsigned int __v = le16_to_cpu((__force __le16)__raw_readw(p)); __iormb(); __v; }) #define ioread32(p) ({ unsigned int __v = le32_to_cpu((__force __le32)__raw_readl(p)); __iormb(); __v; }) +#define ioread16be(p) ({ unsigned int __v = be16_to_cpu((__force __be16)__raw_readw(p)); __iormb(); __v; }) +#define ioread32be(p) ({ unsigned int __v = be32_to_cpu((__force __be32)__raw_readl(p)); __iormb(); __v; }) + #define iowrite8(v,p) ({ __iowmb(); (void)__raw_writeb(v, p); }) #define iowrite16(v,p) ({ __iowmb(); (void)__raw_writew((__force __u16)cpu_to_le16(v), p); }) #define iowrite32(v,p) ({ __iowmb(); (void)__raw_writel((__force __u32)cpu_to_le32(v), p); }) +#define iowrite16be(v,p) ({ __iowmb(); (void)__raw_writew((__force __u16)cpu_to_be16(v), p); }) +#define iowrite32be(v,p) ({ __iowmb(); (void)__raw_writel((__force __u32)cpu_to_be32(v), p); }) + #define ioread8_rep(p,d,c) __raw_readsb(p,d,c) #define ioread16_rep(p,d,c) __raw_readsw(p,d,c) #define ioread32_rep(p,d,c) __raw_readsl(p,d,c) diff --git a/arch/arm/include/asm/ioctl.h b/arch/arm/include/asm/ioctl.h deleted file mode 100644 index b279fe06dfe5bea925eccf4b39c8908b23379b6a..0000000000000000000000000000000000000000 --- a/arch/arm/include/asm/ioctl.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/arm/include/asm/irq_regs.h b/arch/arm/include/asm/irq_regs.h deleted file mode 100644 index 3dd9c0b702704abfe23c0b8085f0fd84dcd3f5d5..0000000000000000000000000000000000000000 --- a/arch/arm/include/asm/irq_regs.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/arm/include/asm/kdebug.h b/arch/arm/include/asm/kdebug.h deleted file mode 100644 index 6ece1b0376655be5d6ab0fbcdbc6369f7f68acac..0000000000000000000000000000000000000000 --- a/arch/arm/include/asm/kdebug.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/arm/include/asm/local.h b/arch/arm/include/asm/local.h deleted file mode 100644 index c11c530f74d02877738b3b6edb5d59102a9bf01c..0000000000000000000000000000000000000000 --- a/arch/arm/include/asm/local.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/arm/include/asm/local64.h b/arch/arm/include/asm/local64.h deleted file mode 100644 index 36c93b5cc239b63b42fd2bdf44557e093f780e19..0000000000000000000000000000000000000000 --- a/arch/arm/include/asm/local64.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/arm/include/asm/localtimer.h b/arch/arm/include/asm/localtimer.h index ff66638ff54d5ad7067e4f246d392059eef1a7bf..c6a18424888ed4992ed05913e77e262eb3126723 100644 --- a/arch/arm/include/asm/localtimer.h +++ b/arch/arm/include/asm/localtimer.h @@ -11,6 +11,7 @@ #define __ASM_ARM_LOCALTIMER_H #include +#include struct clock_event_device; @@ -19,27 +20,20 @@ struct clock_event_device; */ void percpu_timer_setup(void); -/* - * Called from assembly, this is the local timer IRQ handler - */ -asmlinkage void do_local_timer(struct pt_regs *); - - #ifdef CONFIG_LOCAL_TIMERS #ifdef CONFIG_HAVE_ARM_TWD #include "smp_twd.h" -#define local_timer_ack() twd_timer_ack() +#define local_timer_stop(c) twd_timer_stop((c)) #else /* - * Platform provides this to acknowledge a local timer IRQ. - * Returns true if the local timer IRQ is to be processed. + * Stop the local timer */ -int local_timer_ack(void); +void local_timer_stop(struct clock_event_device *); #endif @@ -54,6 +48,10 @@ static inline int local_timer_setup(struct clock_event_device *evt) { return -ENXIO; } + +static inline void local_timer_stop(struct clock_event_device *evt) +{ +} #endif #endif diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h index 217aa1911dd7a01641a8d9e85220c2128d263b0b..7d19425dd496a083eb98557bafe2980843bc9fa3 100644 --- a/arch/arm/include/asm/mach/arch.h +++ b/arch/arm/include/asm/mach/arch.h @@ -17,7 +17,7 @@ struct sys_timer; struct machine_desc { unsigned int nr; /* architecture number */ const char *name; /* architecture name */ - unsigned long boot_params; /* tagged list */ + unsigned long atag_offset; /* tagged list (relative) */ const char **dt_compat; /* array of device tree * 'compatible' strings */ @@ -34,8 +34,7 @@ struct machine_desc { unsigned int reserve_lp1 :1; /* never has lp1 */ unsigned int reserve_lp2 :1; /* never has lp2 */ unsigned int soft_reboot :1; /* soft reboot */ - void (*fixup)(struct machine_desc *, - struct tag *, char **, + void (*fixup)(struct tag *, char **, struct meminfo *); void (*reserve)(void);/* reserve mem blocks */ void (*map_io)(void);/* IO mapping function */ diff --git a/arch/arm/include/asm/mach/map.h b/arch/arm/include/asm/mach/map.h index d2fedb5aeb1f381d74dbdfd29516fbbfd0ea4e13..b36f3654bf54ebcc9e1c9617663c706d81bcfd97 100644 --- a/arch/arm/include/asm/mach/map.h +++ b/arch/arm/include/asm/mach/map.h @@ -29,6 +29,7 @@ struct map_desc { #define MT_MEMORY_NONCACHED 11 #define MT_MEMORY_DTCM 12 #define MT_MEMORY_ITCM 13 +#define MT_MEMORY_SO 14 #ifdef CONFIG_MMU extern void iotable_init(struct map_desc *, int); diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index b8de516e600e855e4ece64e3a654a1d451626603..a8997d71084e23b9343b27b650166ba715b96db1 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h @@ -16,9 +16,12 @@ #include #include #include -#include #include +#ifdef CONFIG_NEED_MACH_MEMORY_H +#include +#endif + /* * Allow for constants defined here to be used from assembly code * by prepending the UL suffix only with actual C code compilation. @@ -77,16 +80,7 @@ */ #define IOREMAP_MAX_ORDER 24 -/* - * Size of DMA-consistent memory region. Must be multiple of 2M, - * between 2MB and 14MB inclusive. - */ -#ifndef CONSISTENT_DMA_SIZE -#define CONSISTENT_DMA_SIZE SZ_2M -#endif - #define CONSISTENT_END (0xffe00000UL) -#define CONSISTENT_BASE (CONSISTENT_END - CONSISTENT_DMA_SIZE) #else /* CONFIG_MMU */ @@ -160,7 +154,6 @@ * so that all we need to do is modify the 8-bit constant field. */ #define __PV_BITS_31_24 0x81000000 -#define __PV_BITS_23_16 0x00810000 extern unsigned long __pv_phys_offset; #define PHYS_OFFSET __pv_phys_offset @@ -178,9 +171,6 @@ static inline unsigned long __virt_to_phys(unsigned long x) { unsigned long t; __pv_stub(x, t, "add", __PV_BITS_31_24); -#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT - __pv_stub(t, t, "add", __PV_BITS_23_16); -#endif return t; } @@ -188,9 +178,6 @@ static inline unsigned long __phys_to_virt(unsigned long x) { unsigned long t; __pv_stub(x, t, "sub", __PV_BITS_31_24); -#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT - __pv_stub(t, t, "sub", __PV_BITS_23_16); -#endif return t; } #else @@ -200,7 +187,11 @@ static inline unsigned long __phys_to_virt(unsigned long x) #endif #ifndef PHYS_OFFSET +#ifdef PLAT_PHYS_OFFSET #define PHYS_OFFSET PLAT_PHYS_OFFSET +#else +#define PHYS_OFFSET UL(CONFIG_PHYS_OFFSET) +#endif #endif /* diff --git a/arch/arm/include/asm/mmu.h b/arch/arm/include/asm/mmu.h index b4ffe9d5b5262bbdf01f82218144d74d0823005c..14965658a923c5e99c009292ddc99f06d013738a 100644 --- a/arch/arm/include/asm/mmu.h +++ b/arch/arm/include/asm/mmu.h @@ -6,7 +6,7 @@ typedef struct { #ifdef CONFIG_CPU_HAS_ASID unsigned int id; - spinlock_t id_lock; + raw_spinlock_t id_lock; #endif unsigned int kvm_seq; } mm_context_t; @@ -16,7 +16,7 @@ typedef struct { /* init_mm.context.id_lock should be initialized. */ #define INIT_MM_CONTEXT(name) \ - .context.id_lock = __SPIN_LOCK_UNLOCKED(name.context.id_lock), + .context.id_lock = __RAW_SPIN_LOCK_UNLOCKED(name.context.id_lock), #else #define ASID(mm) (0) #endif diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h index 543b44916d2c59c76abe930c5ea23116d77f77a1..6c6809f982f12557a6fa23a711f095c9a122fdb0 100644 --- a/arch/arm/include/asm/module.h +++ b/arch/arm/include/asm/module.h @@ -31,11 +31,7 @@ struct mod_arch_specific { /* Add __virt_to_phys patching state as well */ #ifdef CONFIG_ARM_PATCH_PHYS_VIRT -#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT -#define MODULE_ARCH_VERMAGIC_P2V "p2v16 " -#else #define MODULE_ARCH_VERMAGIC_P2V "p2v8 " -#endif #else #define MODULE_ARCH_VERMAGIC_P2V "" #endif diff --git a/arch/arm/include/asm/outercache.h b/arch/arm/include/asm/outercache.h index d8387437ec5aa8c49258d9ab9f3bbeca2b6bd189..53426c66352a1bde6f1b3fb510f404ea41ba3206 100644 --- a/arch/arm/include/asm/outercache.h +++ b/arch/arm/include/asm/outercache.h @@ -34,6 +34,7 @@ struct outer_cache_fns { void (*sync)(void); #endif void (*set_debug)(unsigned long); + void (*resume)(void); }; #ifdef CONFIG_OUTER_CACHE @@ -74,6 +75,12 @@ static inline void outer_disable(void) outer_cache.disable(); } +static inline void outer_resume(void) +{ + if (outer_cache.resume) + outer_cache.resume(); +} + #else static inline void outer_inv_range(phys_addr_t start, phys_addr_t end) diff --git a/arch/arm/include/asm/page.h b/arch/arm/include/asm/page.h index ac75d08488892f22dace530691de9a001d884f48..ca94653f1ecbd7ebcbab8079db0d0b74de497ea8 100644 --- a/arch/arm/include/asm/page.h +++ b/arch/arm/include/asm/page.h @@ -151,47 +151,7 @@ extern void __cpu_copy_user_highpage(struct page *to, struct page *from, #define clear_page(page) memset((void *)(page), 0, PAGE_SIZE) extern void copy_page(void *to, const void *from); -typedef unsigned long pteval_t; - -#undef STRICT_MM_TYPECHECKS - -#ifdef STRICT_MM_TYPECHECKS -/* - * These are used to make use of C type-checking.. - */ -typedef struct { pteval_t pte; } pte_t; -typedef struct { unsigned long pmd; } pmd_t; -typedef struct { unsigned long pgd[2]; } pgd_t; -typedef struct { unsigned long pgprot; } pgprot_t; - -#define pte_val(x) ((x).pte) -#define pmd_val(x) ((x).pmd) -#define pgd_val(x) ((x).pgd[0]) -#define pgprot_val(x) ((x).pgprot) - -#define __pte(x) ((pte_t) { (x) } ) -#define __pmd(x) ((pmd_t) { (x) } ) -#define __pgprot(x) ((pgprot_t) { (x) } ) - -#else -/* - * .. while these make it easier on the compiler - */ -typedef pteval_t pte_t; -typedef unsigned long pmd_t; -typedef unsigned long pgd_t[2]; -typedef unsigned long pgprot_t; - -#define pte_val(x) (x) -#define pmd_val(x) (x) -#define pgd_val(x) ((x)[0]) -#define pgprot_val(x) (x) - -#define __pte(x) (x) -#define __pmd(x) (x) -#define __pgprot(x) (x) - -#endif /* STRICT_MM_TYPECHECKS */ +#include #endif /* CONFIG_MMU */ diff --git a/arch/arm/include/asm/percpu.h b/arch/arm/include/asm/percpu.h deleted file mode 100644 index b4e32d8ec072a27ff1421b57300791437be630d7..0000000000000000000000000000000000000000 --- a/arch/arm/include/asm/percpu.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ARM_PERCPU -#define __ARM_PERCPU - -#include - -#endif diff --git a/arch/arm/include/asm/pgalloc.h b/arch/arm/include/asm/pgalloc.h index 22de005f159ce7599166d749fdf8cfdea0905512..3e08fd3fbb6bc5772688b8001aebfb5ad1e16acd 100644 --- a/arch/arm/include/asm/pgalloc.h +++ b/arch/arm/include/asm/pgalloc.h @@ -105,9 +105,9 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t pte) } static inline void __pmd_populate(pmd_t *pmdp, phys_addr_t pte, - unsigned long prot) + pmdval_t prot) { - unsigned long pmdval = (pte + PTE_HWTABLE_OFF) | prot; + pmdval_t pmdval = (pte + PTE_HWTABLE_OFF) | prot; pmdp[0] = __pmd(pmdval); pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t)); flush_pmd_entry(pmdp); diff --git a/arch/arm/include/asm/pgtable-2level-hwdef.h b/arch/arm/include/asm/pgtable-2level-hwdef.h new file mode 100644 index 0000000000000000000000000000000000000000..5cfba15cb401e58d7b291fac12e7395683a9d61f --- /dev/null +++ b/arch/arm/include/asm/pgtable-2level-hwdef.h @@ -0,0 +1,93 @@ +/* + * arch/arm/include/asm/pgtable-2level-hwdef.h + * + * Copyright (C) 1995-2002 Russell King + * + * 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. + */ +#ifndef _ASM_PGTABLE_2LEVEL_HWDEF_H +#define _ASM_PGTABLE_2LEVEL_HWDEF_H + +/* + * Hardware page table definitions. + * + * + Level 1 descriptor (PMD) + * - common + */ +#define PMD_TYPE_MASK (_AT(pmdval_t, 3) << 0) +#define PMD_TYPE_FAULT (_AT(pmdval_t, 0) << 0) +#define PMD_TYPE_TABLE (_AT(pmdval_t, 1) << 0) +#define PMD_TYPE_SECT (_AT(pmdval_t, 2) << 0) +#define PMD_BIT4 (_AT(pmdval_t, 1) << 4) +#define PMD_DOMAIN(x) (_AT(pmdval_t, (x)) << 5) +#define PMD_PROTECTION (_AT(pmdval_t, 1) << 9) /* v5 */ +/* + * - section + */ +#define PMD_SECT_BUFFERABLE (_AT(pmdval_t, 1) << 2) +#define PMD_SECT_CACHEABLE (_AT(pmdval_t, 1) << 3) +#define PMD_SECT_XN (_AT(pmdval_t, 1) << 4) /* v6 */ +#define PMD_SECT_AP_WRITE (_AT(pmdval_t, 1) << 10) +#define PMD_SECT_AP_READ (_AT(pmdval_t, 1) << 11) +#define PMD_SECT_TEX(x) (_AT(pmdval_t, (x)) << 12) /* v5 */ +#define PMD_SECT_APX (_AT(pmdval_t, 1) << 15) /* v6 */ +#define PMD_SECT_S (_AT(pmdval_t, 1) << 16) /* v6 */ +#define PMD_SECT_nG (_AT(pmdval_t, 1) << 17) /* v6 */ +#define PMD_SECT_SUPER (_AT(pmdval_t, 1) << 18) /* v6 */ +#define PMD_SECT_AF (_AT(pmdval_t, 0)) + +#define PMD_SECT_UNCACHED (_AT(pmdval_t, 0)) +#define PMD_SECT_BUFFERED (PMD_SECT_BUFFERABLE) +#define PMD_SECT_WT (PMD_SECT_CACHEABLE) +#define PMD_SECT_WB (PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE) +#define PMD_SECT_MINICACHE (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE) +#define PMD_SECT_WBWA (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE) +#define PMD_SECT_NONSHARED_DEV (PMD_SECT_TEX(2)) + +/* + * - coarse table (not used) + */ + +/* + * + Level 2 descriptor (PTE) + * - common + */ +#define PTE_TYPE_MASK (_AT(pteval_t, 3) << 0) +#define PTE_TYPE_FAULT (_AT(pteval_t, 0) << 0) +#define PTE_TYPE_LARGE (_AT(pteval_t, 1) << 0) +#define PTE_TYPE_SMALL (_AT(pteval_t, 2) << 0) +#define PTE_TYPE_EXT (_AT(pteval_t, 3) << 0) /* v5 */ +#define PTE_BUFFERABLE (_AT(pteval_t, 1) << 2) +#define PTE_CACHEABLE (_AT(pteval_t, 1) << 3) + +/* + * - extended small page/tiny page + */ +#define PTE_EXT_XN (_AT(pteval_t, 1) << 0) /* v6 */ +#define PTE_EXT_AP_MASK (_AT(pteval_t, 3) << 4) +#define PTE_EXT_AP0 (_AT(pteval_t, 1) << 4) +#define PTE_EXT_AP1 (_AT(pteval_t, 2) << 4) +#define PTE_EXT_AP_UNO_SRO (_AT(pteval_t, 0) << 4) +#define PTE_EXT_AP_UNO_SRW (PTE_EXT_AP0) +#define PTE_EXT_AP_URO_SRW (PTE_EXT_AP1) +#define PTE_EXT_AP_URW_SRW (PTE_EXT_AP1|PTE_EXT_AP0) +#define PTE_EXT_TEX(x) (_AT(pteval_t, (x)) << 6) /* v5 */ +#define PTE_EXT_APX (_AT(pteval_t, 1) << 9) /* v6 */ +#define PTE_EXT_COHERENT (_AT(pteval_t, 1) << 9) /* XScale3 */ +#define PTE_EXT_SHARED (_AT(pteval_t, 1) << 10) /* v6 */ +#define PTE_EXT_NG (_AT(pteval_t, 1) << 11) /* v6 */ + +/* + * - small page + */ +#define PTE_SMALL_AP_MASK (_AT(pteval_t, 0xff) << 4) +#define PTE_SMALL_AP_UNO_SRO (_AT(pteval_t, 0x00) << 4) +#define PTE_SMALL_AP_UNO_SRW (_AT(pteval_t, 0x55) << 4) +#define PTE_SMALL_AP_URO_SRW (_AT(pteval_t, 0xaa) << 4) +#define PTE_SMALL_AP_URW_SRW (_AT(pteval_t, 0xff) << 4) + +#define PHYS_MASK (~0UL) + +#endif diff --git a/arch/arm/include/asm/pgtable-2level-types.h b/arch/arm/include/asm/pgtable-2level-types.h new file mode 100644 index 0000000000000000000000000000000000000000..66cb5b0e89c51e882add456bb36cefcf7f5ce31d --- /dev/null +++ b/arch/arm/include/asm/pgtable-2level-types.h @@ -0,0 +1,67 @@ +/* + * arch/arm/include/asm/pgtable-2level-types.h + * + * Copyright (C) 1995-2003 Russell King + * + * 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 + */ +#ifndef _ASM_PGTABLE_2LEVEL_TYPES_H +#define _ASM_PGTABLE_2LEVEL_TYPES_H + +#include + +typedef u32 pteval_t; +typedef u32 pmdval_t; + +#undef STRICT_MM_TYPECHECKS + +#ifdef STRICT_MM_TYPECHECKS +/* + * These are used to make use of C type-checking.. + */ +typedef struct { pteval_t pte; } pte_t; +typedef struct { pmdval_t pmd; } pmd_t; +typedef struct { pmdval_t pgd[2]; } pgd_t; +typedef struct { pteval_t pgprot; } pgprot_t; + +#define pte_val(x) ((x).pte) +#define pmd_val(x) ((x).pmd) +#define pgd_val(x) ((x).pgd[0]) +#define pgprot_val(x) ((x).pgprot) + +#define __pte(x) ((pte_t) { (x) } ) +#define __pmd(x) ((pmd_t) { (x) } ) +#define __pgprot(x) ((pgprot_t) { (x) } ) + +#else +/* + * .. while these make it easier on the compiler + */ +typedef pteval_t pte_t; +typedef pmdval_t pmd_t; +typedef pmdval_t pgd_t[2]; +typedef pteval_t pgprot_t; + +#define pte_val(x) (x) +#define pmd_val(x) (x) +#define pgd_val(x) ((x)[0]) +#define pgprot_val(x) (x) + +#define __pte(x) (x) +#define __pmd(x) (x) +#define __pgprot(x) (x) + +#endif /* STRICT_MM_TYPECHECKS */ + +#endif /* _ASM_PGTABLE_2LEVEL_TYPES_H */ diff --git a/arch/arm/include/asm/pgtable-2level.h b/arch/arm/include/asm/pgtable-2level.h new file mode 100644 index 0000000000000000000000000000000000000000..470457e1cfc5e121158037e6a1db6fead1eb3602 --- /dev/null +++ b/arch/arm/include/asm/pgtable-2level.h @@ -0,0 +1,143 @@ +/* + * arch/arm/include/asm/pgtable-2level.h + * + * Copyright (C) 1995-2002 Russell King + * + * 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. + */ +#ifndef _ASM_PGTABLE_2LEVEL_H +#define _ASM_PGTABLE_2LEVEL_H + +/* + * Hardware-wise, we have a two level page table structure, where the first + * level has 4096 entries, and the second level has 256 entries. Each entry + * is one 32-bit word. Most of the bits in the second level entry are used + * by hardware, and there aren't any "accessed" and "dirty" bits. + * + * Linux on the other hand has a three level page table structure, which can + * be wrapped to fit a two level page table structure easily - using the PGD + * and PTE only. However, Linux also expects one "PTE" table per page, and + * at least a "dirty" bit. + * + * Therefore, we tweak the implementation slightly - we tell Linux that we + * have 2048 entries in the first level, each of which is 8 bytes (iow, two + * hardware pointers to the second level.) The second level contains two + * hardware PTE tables arranged contiguously, preceded by Linux versions + * which contain the state information Linux needs. We, therefore, end up + * with 512 entries in the "PTE" level. + * + * This leads to the page tables having the following layout: + * + * pgd pte + * | | + * +--------+ + * | | +------------+ +0 + * +- - - - + | Linux pt 0 | + * | | +------------+ +1024 + * +--------+ +0 | Linux pt 1 | + * | |-----> +------------+ +2048 + * +- - - - + +4 | h/w pt 0 | + * | |-----> +------------+ +3072 + * +--------+ +8 | h/w pt 1 | + * | | +------------+ +4096 + * + * See L_PTE_xxx below for definitions of bits in the "Linux pt", and + * PTE_xxx for definitions of bits appearing in the "h/w pt". + * + * PMD_xxx definitions refer to bits in the first level page table. + * + * The "dirty" bit is emulated by only granting hardware write permission + * iff the page is marked "writable" and "dirty" in the Linux PTE. This + * means that a write to a clean page will cause a permission fault, and + * the Linux MM layer will mark the page dirty via handle_pte_fault(). + * For the hardware to notice the permission change, the TLB entry must + * be flushed, and ptep_set_access_flags() does that for us. + * + * The "accessed" or "young" bit is emulated by a similar method; we only + * allow accesses to the page if the "young" bit is set. Accesses to the + * page will cause a fault, and handle_pte_fault() will set the young bit + * for us as long as the page is marked present in the corresponding Linux + * PTE entry. Again, ptep_set_access_flags() will ensure that the TLB is + * up to date. + * + * However, when the "young" bit is cleared, we deny access to the page + * by clearing the hardware PTE. Currently Linux does not flush the TLB + * for us in this case, which means the TLB will retain the transation + * until either the TLB entry is evicted under pressure, or a context + * switch which changes the user space mapping occurs. + */ +#define PTRS_PER_PTE 512 +#define PTRS_PER_PMD 1 +#define PTRS_PER_PGD 2048 + +#define PTE_HWTABLE_PTRS (PTRS_PER_PTE) +#define PTE_HWTABLE_OFF (PTE_HWTABLE_PTRS * sizeof(pte_t)) +#define PTE_HWTABLE_SIZE (PTRS_PER_PTE * sizeof(u32)) + +/* + * PMD_SHIFT determines the size of the area a second-level page table can map + * PGDIR_SHIFT determines what a third-level page table entry can map + */ +#define PMD_SHIFT 21 +#define PGDIR_SHIFT 21 + +#define PMD_SIZE (1UL << PMD_SHIFT) +#define PMD_MASK (~(PMD_SIZE-1)) +#define PGDIR_SIZE (1UL << PGDIR_SHIFT) +#define PGDIR_MASK (~(PGDIR_SIZE-1)) + +/* + * section address mask and size definitions. + */ +#define SECTION_SHIFT 20 +#define SECTION_SIZE (1UL << SECTION_SHIFT) +#define SECTION_MASK (~(SECTION_SIZE-1)) + +/* + * ARMv6 supersection address mask and size definitions. + */ +#define SUPERSECTION_SHIFT 24 +#define SUPERSECTION_SIZE (1UL << SUPERSECTION_SHIFT) +#define SUPERSECTION_MASK (~(SUPERSECTION_SIZE-1)) + +#define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE) + +/* + * "Linux" PTE definitions. + * + * We keep two sets of PTEs - the hardware and the linux version. + * This allows greater flexibility in the way we map the Linux bits + * onto the hardware tables, and allows us to have YOUNG and DIRTY + * bits. + * + * The PTE table pointer refers to the hardware entries; the "Linux" + * entries are stored 1024 bytes below. + */ +#define L_PTE_PRESENT (_AT(pteval_t, 1) << 0) +#define L_PTE_YOUNG (_AT(pteval_t, 1) << 1) +#define L_PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !PRESENT */ +#define L_PTE_DIRTY (_AT(pteval_t, 1) << 6) +#define L_PTE_RDONLY (_AT(pteval_t, 1) << 7) +#define L_PTE_USER (_AT(pteval_t, 1) << 8) +#define L_PTE_XN (_AT(pteval_t, 1) << 9) +#define L_PTE_SHARED (_AT(pteval_t, 1) << 10) /* shared(v6), coherent(xsc3) */ + +/* + * These are the memory types, defined to be compatible with + * pre-ARMv6 CPUs cacheable and bufferable bits: XXCB + */ +#define L_PTE_MT_UNCACHED (_AT(pteval_t, 0x00) << 2) /* 0000 */ +#define L_PTE_MT_BUFFERABLE (_AT(pteval_t, 0x01) << 2) /* 0001 */ +#define L_PTE_MT_WRITETHROUGH (_AT(pteval_t, 0x02) << 2) /* 0010 */ +#define L_PTE_MT_WRITEBACK (_AT(pteval_t, 0x03) << 2) /* 0011 */ +#define L_PTE_MT_MINICACHE (_AT(pteval_t, 0x06) << 2) /* 0110 (sa1100, xscale) */ +#define L_PTE_MT_WRITEALLOC (_AT(pteval_t, 0x07) << 2) /* 0111 */ +#define L_PTE_MT_DEV_SHARED (_AT(pteval_t, 0x04) << 2) /* 0100 */ +#define L_PTE_MT_DEV_NONSHARED (_AT(pteval_t, 0x0c) << 2) /* 1100 */ +#define L_PTE_MT_DEV_WC (_AT(pteval_t, 0x09) << 2) /* 1001 */ +#define L_PTE_MT_DEV_CACHED (_AT(pteval_t, 0x0b) << 2) /* 1011 */ +#define L_PTE_MT_MASK (_AT(pteval_t, 0x0f) << 2) + +#endif /* _ASM_PGTABLE_2LEVEL_H */ diff --git a/arch/arm/include/asm/pgtable-hwdef.h b/arch/arm/include/asm/pgtable-hwdef.h index fd1521d5cb9dd97e07e8f5a54b7994295294a7d3..183111164ce93cc3c3ec3e1502c9b4fb8c53934c 100644 --- a/arch/arm/include/asm/pgtable-hwdef.h +++ b/arch/arm/include/asm/pgtable-hwdef.h @@ -10,81 +10,6 @@ #ifndef _ASMARM_PGTABLE_HWDEF_H #define _ASMARM_PGTABLE_HWDEF_H -/* - * Hardware page table definitions. - * - * + Level 1 descriptor (PMD) - * - common - */ -#define PMD_TYPE_MASK (3 << 0) -#define PMD_TYPE_FAULT (0 << 0) -#define PMD_TYPE_TABLE (1 << 0) -#define PMD_TYPE_SECT (2 << 0) -#define PMD_BIT4 (1 << 4) -#define PMD_DOMAIN(x) ((x) << 5) -#define PMD_PROTECTION (1 << 9) /* v5 */ -/* - * - section - */ -#define PMD_SECT_BUFFERABLE (1 << 2) -#define PMD_SECT_CACHEABLE (1 << 3) -#define PMD_SECT_XN (1 << 4) /* v6 */ -#define PMD_SECT_AP_WRITE (1 << 10) -#define PMD_SECT_AP_READ (1 << 11) -#define PMD_SECT_TEX(x) ((x) << 12) /* v5 */ -#define PMD_SECT_APX (1 << 15) /* v6 */ -#define PMD_SECT_S (1 << 16) /* v6 */ -#define PMD_SECT_nG (1 << 17) /* v6 */ -#define PMD_SECT_SUPER (1 << 18) /* v6 */ - -#define PMD_SECT_UNCACHED (0) -#define PMD_SECT_BUFFERED (PMD_SECT_BUFFERABLE) -#define PMD_SECT_WT (PMD_SECT_CACHEABLE) -#define PMD_SECT_WB (PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE) -#define PMD_SECT_MINICACHE (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE) -#define PMD_SECT_WBWA (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE) -#define PMD_SECT_NONSHARED_DEV (PMD_SECT_TEX(2)) - -/* - * - coarse table (not used) - */ - -/* - * + Level 2 descriptor (PTE) - * - common - */ -#define PTE_TYPE_MASK (3 << 0) -#define PTE_TYPE_FAULT (0 << 0) -#define PTE_TYPE_LARGE (1 << 0) -#define PTE_TYPE_SMALL (2 << 0) -#define PTE_TYPE_EXT (3 << 0) /* v5 */ -#define PTE_BUFFERABLE (1 << 2) -#define PTE_CACHEABLE (1 << 3) - -/* - * - extended small page/tiny page - */ -#define PTE_EXT_XN (1 << 0) /* v6 */ -#define PTE_EXT_AP_MASK (3 << 4) -#define PTE_EXT_AP0 (1 << 4) -#define PTE_EXT_AP1 (2 << 4) -#define PTE_EXT_AP_UNO_SRO (0 << 4) -#define PTE_EXT_AP_UNO_SRW (PTE_EXT_AP0) -#define PTE_EXT_AP_URO_SRW (PTE_EXT_AP1) -#define PTE_EXT_AP_URW_SRW (PTE_EXT_AP1|PTE_EXT_AP0) -#define PTE_EXT_TEX(x) ((x) << 6) /* v5 */ -#define PTE_EXT_APX (1 << 9) /* v6 */ -#define PTE_EXT_COHERENT (1 << 9) /* XScale3 */ -#define PTE_EXT_SHARED (1 << 10) /* v6 */ -#define PTE_EXT_NG (1 << 11) /* v6 */ - -/* - * - small page - */ -#define PTE_SMALL_AP_MASK (0xff << 4) -#define PTE_SMALL_AP_UNO_SRO (0x00 << 4) -#define PTE_SMALL_AP_UNO_SRW (0x55 << 4) -#define PTE_SMALL_AP_URO_SRW (0xaa << 4) -#define PTE_SMALL_AP_URW_SRW (0xff << 4) +#include #endif diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index 5750704e02718b9247704021a0832f161bcbaf3b..9451dce3a5530f9c50c9a34d9ef84e2366a9bbab 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -24,6 +24,8 @@ #include #include +#include + /* * Just any arbitrary offset to the start of the vmalloc VM area: the * current 8MB value just means that there will be a 8MB "hole" after the @@ -41,79 +43,6 @@ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) #endif -/* - * Hardware-wise, we have a two level page table structure, where the first - * level has 4096 entries, and the second level has 256 entries. Each entry - * is one 32-bit word. Most of the bits in the second level entry are used - * by hardware, and there aren't any "accessed" and "dirty" bits. - * - * Linux on the other hand has a three level page table structure, which can - * be wrapped to fit a two level page table structure easily - using the PGD - * and PTE only. However, Linux also expects one "PTE" table per page, and - * at least a "dirty" bit. - * - * Therefore, we tweak the implementation slightly - we tell Linux that we - * have 2048 entries in the first level, each of which is 8 bytes (iow, two - * hardware pointers to the second level.) The second level contains two - * hardware PTE tables arranged contiguously, preceded by Linux versions - * which contain the state information Linux needs. We, therefore, end up - * with 512 entries in the "PTE" level. - * - * This leads to the page tables having the following layout: - * - * pgd pte - * | | - * +--------+ - * | | +------------+ +0 - * +- - - - + | Linux pt 0 | - * | | +------------+ +1024 - * +--------+ +0 | Linux pt 1 | - * | |-----> +------------+ +2048 - * +- - - - + +4 | h/w pt 0 | - * | |-----> +------------+ +3072 - * +--------+ +8 | h/w pt 1 | - * | | +------------+ +4096 - * - * See L_PTE_xxx below for definitions of bits in the "Linux pt", and - * PTE_xxx for definitions of bits appearing in the "h/w pt". - * - * PMD_xxx definitions refer to bits in the first level page table. - * - * The "dirty" bit is emulated by only granting hardware write permission - * iff the page is marked "writable" and "dirty" in the Linux PTE. This - * means that a write to a clean page will cause a permission fault, and - * the Linux MM layer will mark the page dirty via handle_pte_fault(). - * For the hardware to notice the permission change, the TLB entry must - * be flushed, and ptep_set_access_flags() does that for us. - * - * The "accessed" or "young" bit is emulated by a similar method; we only - * allow accesses to the page if the "young" bit is set. Accesses to the - * page will cause a fault, and handle_pte_fault() will set the young bit - * for us as long as the page is marked present in the corresponding Linux - * PTE entry. Again, ptep_set_access_flags() will ensure that the TLB is - * up to date. - * - * However, when the "young" bit is cleared, we deny access to the page - * by clearing the hardware PTE. Currently Linux does not flush the TLB - * for us in this case, which means the TLB will retain the transation - * until either the TLB entry is evicted under pressure, or a context - * switch which changes the user space mapping occurs. - */ -#define PTRS_PER_PTE 512 -#define PTRS_PER_PMD 1 -#define PTRS_PER_PGD 2048 - -#define PTE_HWTABLE_PTRS (PTRS_PER_PTE) -#define PTE_HWTABLE_OFF (PTE_HWTABLE_PTRS * sizeof(pte_t)) -#define PTE_HWTABLE_SIZE (PTRS_PER_PTE * sizeof(u32)) - -/* - * PMD_SHIFT determines the size of the area a second-level page table can map - * PGDIR_SHIFT determines what a third-level page table entry can map - */ -#define PMD_SHIFT 21 -#define PGDIR_SHIFT 21 - #define LIBRARY_TEXT_START 0x0c000000 #ifndef __ASSEMBLY__ @@ -124,12 +53,6 @@ extern void __pgd_error(const char *file, int line, pgd_t); #define pte_ERROR(pte) __pte_error(__FILE__, __LINE__, pte) #define pmd_ERROR(pmd) __pmd_error(__FILE__, __LINE__, pmd) #define pgd_ERROR(pgd) __pgd_error(__FILE__, __LINE__, pgd) -#endif /* !__ASSEMBLY__ */ - -#define PMD_SIZE (1UL << PMD_SHIFT) -#define PMD_MASK (~(PMD_SIZE-1)) -#define PGDIR_SIZE (1UL << PGDIR_SHIFT) -#define PGDIR_MASK (~(PGDIR_SIZE-1)) /* * This is the lowest virtual address we can permit any user space @@ -138,60 +61,6 @@ extern void __pgd_error(const char *file, int line, pgd_t); */ #define FIRST_USER_ADDRESS PAGE_SIZE -#define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE) - -/* - * section address mask and size definitions. - */ -#define SECTION_SHIFT 20 -#define SECTION_SIZE (1UL << SECTION_SHIFT) -#define SECTION_MASK (~(SECTION_SIZE-1)) - -/* - * ARMv6 supersection address mask and size definitions. - */ -#define SUPERSECTION_SHIFT 24 -#define SUPERSECTION_SIZE (1UL << SUPERSECTION_SHIFT) -#define SUPERSECTION_MASK (~(SUPERSECTION_SIZE-1)) - -/* - * "Linux" PTE definitions. - * - * We keep two sets of PTEs - the hardware and the linux version. - * This allows greater flexibility in the way we map the Linux bits - * onto the hardware tables, and allows us to have YOUNG and DIRTY - * bits. - * - * The PTE table pointer refers to the hardware entries; the "Linux" - * entries are stored 1024 bytes below. - */ -#define L_PTE_PRESENT (_AT(pteval_t, 1) << 0) -#define L_PTE_YOUNG (_AT(pteval_t, 1) << 1) -#define L_PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !PRESENT */ -#define L_PTE_DIRTY (_AT(pteval_t, 1) << 6) -#define L_PTE_RDONLY (_AT(pteval_t, 1) << 7) -#define L_PTE_USER (_AT(pteval_t, 1) << 8) -#define L_PTE_XN (_AT(pteval_t, 1) << 9) -#define L_PTE_SHARED (_AT(pteval_t, 1) << 10) /* shared(v6), coherent(xsc3) */ - -/* - * These are the memory types, defined to be compatible with - * pre-ARMv6 CPUs cacheable and bufferable bits: XXCB - */ -#define L_PTE_MT_UNCACHED (_AT(pteval_t, 0x00) << 2) /* 0000 */ -#define L_PTE_MT_BUFFERABLE (_AT(pteval_t, 0x01) << 2) /* 0001 */ -#define L_PTE_MT_WRITETHROUGH (_AT(pteval_t, 0x02) << 2) /* 0010 */ -#define L_PTE_MT_WRITEBACK (_AT(pteval_t, 0x03) << 2) /* 0011 */ -#define L_PTE_MT_MINICACHE (_AT(pteval_t, 0x06) << 2) /* 0110 (sa1100, xscale) */ -#define L_PTE_MT_WRITEALLOC (_AT(pteval_t, 0x07) << 2) /* 0111 */ -#define L_PTE_MT_DEV_SHARED (_AT(pteval_t, 0x04) << 2) /* 0100 */ -#define L_PTE_MT_DEV_NONSHARED (_AT(pteval_t, 0x0c) << 2) /* 1100 */ -#define L_PTE_MT_DEV_WC (_AT(pteval_t, 0x09) << 2) /* 1001 */ -#define L_PTE_MT_DEV_CACHED (_AT(pteval_t, 0x0b) << 2) /* 1011 */ -#define L_PTE_MT_MASK (_AT(pteval_t, 0x0f) << 2) - -#ifndef __ASSEMBLY__ - /* * The pgprot_* and protection_map entries will be fixed up in runtime * to include the cachable and bufferable bits based on memory policy, @@ -232,6 +101,9 @@ extern pgprot_t pgprot_kernel; #define pgprot_writecombine(prot) \ __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE) +#define pgprot_stronglyordered(prot) \ + __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED) + #ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE #define pgprot_dmacoherent(prot) \ __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE | L_PTE_XN) @@ -327,10 +199,10 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; static inline pte_t *pmd_page_vaddr(pmd_t pmd) { - return __va(pmd_val(pmd) & PAGE_MASK); + return __va(pmd_val(pmd) & PHYS_MASK & (s32)PAGE_MASK); } -#define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd))) +#define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK)) /* we don't need complex calculations here as the pmd is folded into the pgd */ #define pmd_addr_end(addr,end) (end) @@ -351,7 +223,7 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd) #define pte_offset_map(pmd,addr) (__pte_map(pmd) + pte_index(addr)) #define pte_unmap(pte) __pte_unmap(pte) -#define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT) +#define pte_pfn(pte) ((pte_val(pte) & PHYS_MASK) >> PAGE_SHIFT) #define pfn_pte(pfn,prot) __pte(__pfn_to_phys(pfn) | pgprot_val(prot)) #define pte_page(pte) pfn_to_page(pte_pfn(pte)) diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h index b7e82c4aced63ed7222df9a92c46810bc3094622..71d99b83cdb980178aac275e487c2db081c041fc 100644 --- a/arch/arm/include/asm/pmu.h +++ b/arch/arm/include/asm/pmu.h @@ -13,7 +13,12 @@ #define __ARM_PMU_H__ #include +#include +/* + * Types of PMUs that can be accessed directly and require mutual + * exclusion between profiling tools. + */ enum arm_pmu_type { ARM_PMU_DEVICE_CPU = 0, ARM_NUM_PMU_DEVICES, @@ -37,21 +42,17 @@ struct arm_pmu_platdata { * reserve_pmu() - reserve the hardware performance counters * * Reserve the hardware performance counters in the system for exclusive use. - * The platform_device for the system is returned on success, ERR_PTR() - * encoded error on failure. + * Returns 0 on success or -EBUSY if the lock is already held. */ -extern struct platform_device * +extern int reserve_pmu(enum arm_pmu_type type); /** * release_pmu() - Relinquish control of the performance counters * * Release the performance counters and allow someone else to use them. - * Callers must have disabled the counters and released IRQs before calling - * this. The platform_device returned from reserve_pmu() must be passed as - * a cookie. */ -extern int +extern void release_pmu(enum arm_pmu_type type); /** @@ -68,24 +69,78 @@ init_pmu(enum arm_pmu_type type); #include -static inline struct platform_device * -reserve_pmu(enum arm_pmu_type type) -{ - return ERR_PTR(-ENODEV); -} - static inline int -release_pmu(enum arm_pmu_type type) +reserve_pmu(enum arm_pmu_type type) { return -ENODEV; } -static inline int -init_pmu(enum arm_pmu_type type) -{ - return -ENODEV; -} +static inline void +release_pmu(enum arm_pmu_type type) { } #endif /* CONFIG_CPU_HAS_PMU */ +#ifdef CONFIG_HW_PERF_EVENTS + +/* The events for a given PMU register set. */ +struct pmu_hw_events { + /* + * The events that are active on the PMU for the given index. + */ + struct perf_event **events; + + /* + * A 1 bit for an index indicates that the counter is being used for + * an event. A 0 means that the counter can be used. + */ + unsigned long *used_mask; + + /* + * Hardware lock to serialize accesses to PMU registers. Needed for the + * read/modify/write sequences. + */ + raw_spinlock_t pmu_lock; +}; + +struct arm_pmu { + struct pmu pmu; + enum arm_perf_pmu_ids id; + enum arm_pmu_type type; + cpumask_t active_irqs; + const char *name; + irqreturn_t (*handle_irq)(int irq_num, void *dev); + void (*enable)(struct hw_perf_event *evt, int idx); + void (*disable)(struct hw_perf_event *evt, int idx); + int (*get_event_idx)(struct pmu_hw_events *hw_events, + struct hw_perf_event *hwc); + int (*set_event_filter)(struct hw_perf_event *evt, + struct perf_event_attr *attr); + u32 (*read_counter)(int idx); + void (*write_counter)(int idx, u32 val); + void (*start)(void); + void (*stop)(void); + void (*reset)(void *); + int (*map_event)(struct perf_event *event); + int num_events; + atomic_t active_events; + struct mutex reserve_mutex; + u64 max_period; + struct platform_device *plat_device; + struct pmu_hw_events *(*get_hw_events)(void); +}; + +#define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu)) + +int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type); + +u64 armpmu_event_update(struct perf_event *event, + struct hw_perf_event *hwc, + int idx, int overflow); + +int armpmu_event_set_period(struct perf_event *event, + struct hw_perf_event *hwc, + int idx); + +#endif /* CONFIG_HW_PERF_EVENTS */ + #endif /* __ARM_PMU_H__ */ diff --git a/arch/arm/include/asm/poll.h b/arch/arm/include/asm/poll.h deleted file mode 100644 index c98509d3149e637951f5edf96116a70ed9d8bc51..0000000000000000000000000000000000000000 --- a/arch/arm/include/asm/poll.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h index 633d1cb84d87cbe356496b863e24f85a5f0402ea..9e92cb205e656e61d1b47a3aed9268dd343db205 100644 --- a/arch/arm/include/asm/proc-fns.h +++ b/arch/arm/include/asm/proc-fns.h @@ -81,6 +81,10 @@ extern void cpu_dcache_clean_area(void *, int); extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm); extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext); extern void cpu_reset(unsigned long addr) __attribute__((noreturn)); + +/* These three are private to arch/arm/kernel/suspend.c */ +extern void cpu_do_suspend(void *); +extern void cpu_do_resume(void *); #else #define cpu_proc_init processor._proc_init #define cpu_proc_fin processor._proc_fin @@ -89,6 +93,10 @@ extern void cpu_reset(unsigned long addr) __attribute__((noreturn)); #define cpu_dcache_clean_area processor.dcache_clean_area #define cpu_set_pte_ext processor.set_pte_ext #define cpu_do_switch_mm processor.switch_mm + +/* These three are private to arch/arm/kernel/suspend.c */ +#define cpu_do_suspend processor.do_suspend +#define cpu_do_resume processor.do_resume #endif extern void cpu_resume(void); diff --git a/arch/arm/include/asm/resource.h b/arch/arm/include/asm/resource.h deleted file mode 100644 index 734b581b5b6acddba242b3cc3c2315a079bf9dc0..0000000000000000000000000000000000000000 --- a/arch/arm/include/asm/resource.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ARM_RESOURCE_H -#define _ARM_RESOURCE_H - -#include - -#endif diff --git a/arch/arm/include/asm/sections.h b/arch/arm/include/asm/sections.h deleted file mode 100644 index 2b8c5160388fb4863f05c33c15e42e22c53fc7a2..0000000000000000000000000000000000000000 --- a/arch/arm/include/asm/sections.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/arm/include/asm/siginfo.h b/arch/arm/include/asm/siginfo.h deleted file mode 100644 index 5e21852e6039d3b479403df986cea3f6ec80fe75..0000000000000000000000000000000000000000 --- a/arch/arm/include/asm/siginfo.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASMARM_SIGINFO_H -#define _ASMARM_SIGINFO_H - -#include - -#endif diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h index e42d96a45d3e9267566cfa662a71235423c1e2f0..1e5717afc4ac007e94447cf91ab88bdee9f7f1ad 100644 --- a/arch/arm/include/asm/smp.h +++ b/arch/arm/include/asm/smp.h @@ -32,6 +32,11 @@ extern void show_ipi_list(struct seq_file *, int); */ asmlinkage void do_IPI(int ipinr, struct pt_regs *regs); +/* + * Called from C code, this handles an IPI. + */ +void handle_IPI(int ipinr, struct pt_regs *regs); + /* * Setup the set of possible CPUs (via set_cpu_possible) */ @@ -65,6 +70,12 @@ extern void platform_secondary_init(unsigned int cpu); */ extern void platform_smp_prepare_cpus(unsigned int); +/* + * Logical CPU mapping. + */ +extern int __cpu_logical_map[NR_CPUS]; +#define cpu_logical_map(cpu) __cpu_logical_map[cpu] + /* * Initial data for bringing up a secondary CPU. */ @@ -88,9 +99,4 @@ extern void platform_cpu_enable(unsigned int cpu); extern void arch_send_call_function_single_ipi(int cpu); extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); -/* - * show local interrupt info - */ -extern void show_local_irqs(struct seq_file *, int); - #endif /* ifndef __ASM_ARM_SMP_H */ diff --git a/arch/arm/include/asm/smp_twd.h b/arch/arm/include/asm/smp_twd.h index fed9981fba08feec85a09b094215036a7e8839b1..ef9ffba97ad8d7633a830349d72da8b189e5bda8 100644 --- a/arch/arm/include/asm/smp_twd.h +++ b/arch/arm/include/asm/smp_twd.h @@ -22,7 +22,7 @@ struct clock_event_device; extern void __iomem *twd_base; -int twd_timer_ack(void); void twd_timer_setup(struct clock_event_device *); +void twd_timer_stop(struct clock_event_device *); #endif diff --git a/arch/arm/include/asm/suspend.h b/arch/arm/include/asm/suspend.h index b0e4e1a0231870c45d14bea0a9178d701737b673..1c0a551ae375490c8f81c589ae92511d509f0bb0 100644 --- a/arch/arm/include/asm/suspend.h +++ b/arch/arm/include/asm/suspend.h @@ -1,22 +1,7 @@ #ifndef __ASM_ARM_SUSPEND_H #define __ASM_ARM_SUSPEND_H -#include -#include - extern void cpu_resume(void); - -/* - * Hide the first two arguments to __cpu_suspend - these are an implementation - * detail which platform code shouldn't have to know about. - */ -static inline int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) -{ - extern int __cpu_suspend(int, long, unsigned long, - int (*)(unsigned long)); - int ret = __cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, arg, fn); - flush_tlb_all(); - return ret; -} +extern int cpu_suspend(unsigned long, int (*)(unsigned long)); #endif diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 832888d0c20c263a761cc093bb96ae4977ed15bc..984014b92647a8a1a093f8b46ce05dfd729ca473 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -57,18 +57,12 @@ #ifndef __ASSEMBLY__ +#include #include #include #include -#define __exception __attribute__((section(".exception.text"))) -#ifdef CONFIG_FUNCTION_GRAPH_TRACER -#define __exception_irq_entry __irq_entry -#else -#define __exception_irq_entry __exception -#endif - struct thread_info; struct task_struct; @@ -97,14 +91,13 @@ void hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int, #define xchg(ptr,x) \ ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) -extern asmlinkage void __backtrace(void); extern asmlinkage void c_backtrace(unsigned long fp, int pmode); struct mm_struct; extern void show_pte(struct mm_struct *mm, unsigned long addr); extern void __show_regs(struct pt_regs *); -extern int cpu_architecture(void); +extern int __pure cpu_architecture(void); extern void cpu_init(void); void arm_machine_restart(char mode, const char *cmd); diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h index 8077145698ffff09f802644021ae9980b8b226a2..02b2f82039828bb0d4b016e41882c3071b686b93 100644 --- a/arch/arm/include/asm/tlbflush.h +++ b/arch/arm/include/asm/tlbflush.h @@ -471,7 +471,7 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr) * these operations. This is typically used when we are removing * PMD entries. */ -static inline void flush_pmd_entry(pmd_t *pmd) +static inline void flush_pmd_entry(void *pmd) { const unsigned int __tlb_flag = __cpu_tlb_flags; @@ -487,7 +487,7 @@ static inline void flush_pmd_entry(pmd_t *pmd) dsb(); } -static inline void clean_pmd_entry(pmd_t *pmd) +static inline void clean_pmd_entry(void *pmd) { const unsigned int __tlb_flag = __cpu_tlb_flags; diff --git a/arch/arm/include/asm/topology.h b/arch/arm/include/asm/topology.h index accbd7cad9b519c4e76994454c19ff9332960be8..a7e457ed27c31e1185ebe3a0eaa745d88c35029d 100644 --- a/arch/arm/include/asm/topology.h +++ b/arch/arm/include/asm/topology.h @@ -1,6 +1,39 @@ #ifndef _ASM_ARM_TOPOLOGY_H #define _ASM_ARM_TOPOLOGY_H +#ifdef CONFIG_ARM_CPU_TOPOLOGY + +#include + +struct cputopo_arm { + int thread_id; + int core_id; + int socket_id; + cpumask_t thread_sibling; + cpumask_t core_sibling; +}; + +extern struct cputopo_arm cpu_topology[NR_CPUS]; + +#define topology_physical_package_id(cpu) (cpu_topology[cpu].socket_id) +#define topology_core_id(cpu) (cpu_topology[cpu].core_id) +#define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_sibling) +#define topology_thread_cpumask(cpu) (&cpu_topology[cpu].thread_sibling) + +#define mc_capable() (cpu_topology[0].socket_id != -1) +#define smt_capable() (cpu_topology[0].thread_id != -1) + +void init_cpu_topology(void); +void store_cpu_topology(unsigned int cpuid); +const struct cpumask *cpu_coregroup_mask(unsigned int cpu); + +#else + +static inline void init_cpu_topology(void) { } +static inline void store_cpu_topology(unsigned int cpuid) { } + +#endif + #include #endif /* _ASM_ARM_TOPOLOGY_H */ diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index f7887dc53c1f6ac8dbda79c63bfd331d51f67a4c..16eed6aebfa45b9b1812001a782d5f9c8247976c 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -29,7 +29,7 @@ obj-$(CONFIG_MODULES) += armksyms.o module.o obj-$(CONFIG_ARTHUR) += arthur.o obj-$(CONFIG_ISA_DMA) += dma-isa.o obj-$(CONFIG_PCI) += bios32.o isa.o -obj-$(CONFIG_PM_SLEEP) += sleep.o +obj-$(CONFIG_ARM_CPU_SUSPEND) += sleep.o suspend.o obj-$(CONFIG_HAVE_SCHED_CLOCK) += sched_clock.o obj-$(CONFIG_SMP) += smp.o smp_tlb.o obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o @@ -43,6 +43,13 @@ obj-$(CONFIG_KPROBES) += kprobes-thumb.o else obj-$(CONFIG_KPROBES) += kprobes-arm.o endif +obj-$(CONFIG_ARM_KPROBES_TEST) += test-kprobes.o +test-kprobes-objs := kprobes-test.o +ifdef CONFIG_THUMB2_KERNEL +test-kprobes-objs += kprobes-test-thumb.o +else +test-kprobes-objs += kprobes-test-arm.o +endif obj-$(CONFIG_ATAGS_PROC) += atags.o obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o obj-$(CONFIG_ARM_THUMBEE) += thumbee.o @@ -66,6 +73,7 @@ obj-$(CONFIG_IWMMXT) += iwmmxt.o obj-$(CONFIG_CPU_HAS_PMU) += pmu.o obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt +obj-$(CONFIG_ARM_CPU_TOPOLOGY) += topology.o ifneq ($(CONFIG_ARCH_EBSA110),y) obj-y += io.o diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index aeef960ff795fce24d2387dd80446072d3bb9263..8e3c6f11b0a1ad00188b2deda119f83bb17ab735 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -49,9 +49,6 @@ extern void __aeabi_ulcmp(void); extern void fpundefinstr(void); - -EXPORT_SYMBOL(__backtrace); - /* platform dependent support */ EXPORT_SYMBOL(__udelay); EXPORT_SYMBOL(__const_udelay); diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c index 16baba2e436961fa9f7128278368b8a5746182d8..1429d8989fb90defcd8ba22fb18493a2206f658d 100644 --- a/arch/arm/kernel/asm-offsets.c +++ b/arch/arm/kernel/asm-offsets.c @@ -20,6 +20,7 @@ #include #include #include +#include #include /* @@ -92,6 +93,17 @@ int main(void) DEFINE(S_OLD_R0, offsetof(struct pt_regs, ARM_ORIG_r0)); DEFINE(S_FRAME_SIZE, sizeof(struct pt_regs)); BLANK(); +#ifdef CONFIG_CACHE_L2X0 + DEFINE(L2X0_R_PHY_BASE, offsetof(struct l2x0_regs, phy_base)); + DEFINE(L2X0_R_AUX_CTRL, offsetof(struct l2x0_regs, aux_ctrl)); + DEFINE(L2X0_R_TAG_LATENCY, offsetof(struct l2x0_regs, tag_latency)); + DEFINE(L2X0_R_DATA_LATENCY, offsetof(struct l2x0_regs, data_latency)); + DEFINE(L2X0_R_FILTER_START, offsetof(struct l2x0_regs, filter_start)); + DEFINE(L2X0_R_FILTER_END, offsetof(struct l2x0_regs, filter_end)); + DEFINE(L2X0_R_PREFETCH_CTRL, offsetof(struct l2x0_regs, prefetch_ctrl)); + DEFINE(L2X0_R_PWR_CTRL, offsetof(struct l2x0_regs, pwr_ctrl)); + BLANK(); +#endif #ifdef CONFIG_CPU_HAS_ASID DEFINE(MM_CONTEXT_ID, offsetof(struct mm_struct, context.id)); BLANK(); diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index d6df359408f096f84c408740e5fef895a0d05a78..c0d9203fc75ec8725df679ab63ecde20ac15c787 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -412,6 +412,9 @@ void pcibios_fixup_bus(struct pci_bus *bus) printk(KERN_INFO "PCI: bus%d: Fast back to back transfers %sabled\n", bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis"); } +#ifdef CONFIG_HOTPLUG +EXPORT_SYMBOL(pcibios_fixup_bus); +#endif /* * Convert from Linux-centric to bus-centric addresses for bridge devices. @@ -431,6 +434,7 @@ pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, region->start = res->start - offset; region->end = res->end - offset; } +EXPORT_SYMBOL(pcibios_resource_to_bus); void __devinit pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, @@ -447,12 +451,7 @@ pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, res->start = region->start + offset; res->end = region->end + offset; } - -#ifdef CONFIG_HOTPLUG -EXPORT_SYMBOL(pcibios_fixup_bus); -EXPORT_SYMBOL(pcibios_resource_to_bus); EXPORT_SYMBOL(pcibios_bus_to_resource); -#endif /* * Swizzle the device pin each time we cross a bridge. diff --git a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S index bcd66e00bdbeec688363cbd0e2178fcc158fcc8a..204e2160cfccbdd5fa88a00285086d73a522ebcb 100644 --- a/arch/arm/kernel/debug.S +++ b/arch/arm/kernel/debug.S @@ -22,7 +22,7 @@ #if defined(CONFIG_DEBUG_ICEDCC) @@ debug using ARM EmbeddedICE DCC channel - .macro addruart, rp, rv + .macro addruart, rp, rv, tmp .endm #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7) @@ -106,7 +106,7 @@ #ifdef CONFIG_MMU .macro addruart_current, rx, tmp1, tmp2 - addruart \tmp1, \tmp2 + addruart \tmp1, \tmp2, \rx mrc p15, 0, \rx, c1, c0 tst \rx, #1 moveq \rx, \tmp1 @@ -151,6 +151,8 @@ printhex: adr r2, hexbuf b printascii ENDPROC(printhex2) +hexbuf: .space 16 + .ltorg ENTRY(printascii) @@ -175,5 +177,3 @@ ENTRY(printch) mov r0, #0 b 1b ENDPROC(printch) - -hexbuf: .space 16 diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c index 2c4a185f92cdc45d2f7b9eab720d46fc9dfe62f4..7b829d9663b1b05b624e1ceda81b927b7a529c36 100644 --- a/arch/arm/kernel/dma.c +++ b/arch/arm/kernel/dma.c @@ -23,7 +23,7 @@ #include -DEFINE_SPINLOCK(dma_spin_lock); +DEFINE_RAW_SPINLOCK(dma_spin_lock); EXPORT_SYMBOL(dma_spin_lock); static dma_t *dma_chan[MAX_DMA_CHANNELS]; diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c index d16500110ee99526655dcf409455ea0b8e32587b..4dd0edab6a658880ed505145fff2c5ce001ae639 100644 --- a/arch/arm/kernel/ecard.c +++ b/arch/arm/kernel/ecard.c @@ -237,7 +237,7 @@ static void ecard_init_pgtables(struct mm_struct *mm) memcpy(dst_pgd, src_pgd, sizeof(pgd_t) * (IO_SIZE / PGDIR_SIZE)); - src_pgd = pgd_offset(mm, EASI_BASE); + src_pgd = pgd_offset(mm, (unsigned long)EASI_BASE); dst_pgd = pgd_offset(mm, EASI_START); memcpy(dst_pgd, src_pgd, sizeof(pgd_t) * (EASI_SIZE / PGDIR_SIZE)); @@ -674,44 +674,37 @@ static int __init ecard_probeirqhw(void) #define ecard_probeirqhw() (0) #endif -#ifndef IO_EC_MEMC8_BASE -#define IO_EC_MEMC8_BASE 0 -#endif - -static unsigned int __ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed) +static void __iomem *__ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed) { - unsigned long address = 0; + void __iomem *address = NULL; int slot = ec->slot_no; if (ec->slot_no == 8) - return IO_EC_MEMC8_BASE; + return ECARD_MEMC8_BASE; ectcr &= ~(1 << slot); switch (type) { case ECARD_MEMC: if (slot < 4) - address = IO_EC_MEMC_BASE + (slot << 12); + address = ECARD_MEMC_BASE + (slot << 14); break; case ECARD_IOC: if (slot < 4) - address = IO_EC_IOC_BASE + (slot << 12); -#ifdef IO_EC_IOC4_BASE + address = ECARD_IOC_BASE + (slot << 14); else - address = IO_EC_IOC4_BASE + ((slot - 4) << 12); -#endif + address = ECARD_IOC4_BASE + ((slot - 4) << 14); if (address) - address += speed << 17; + address += speed << 19; break; -#ifdef IO_EC_EASI_BASE case ECARD_EASI: - address = IO_EC_EASI_BASE + (slot << 22); + address = ECARD_EASI_BASE + (slot << 24); if (speed == ECARD_FAST) ectcr |= 1 << slot; break; -#endif + default: break; } @@ -990,6 +983,7 @@ ecard_probe(int slot, card_type_t type) ecard_t **ecp; ecard_t *ec; struct ex_ecid cid; + void __iomem *addr; int i, rc; ec = ecard_alloc_card(type, slot); @@ -999,7 +993,7 @@ ecard_probe(int slot, card_type_t type) } rc = -ENODEV; - if ((ec->podaddr = __ecard_address(ec, type, ECARD_SYNC)) == 0) + if ((addr = __ecard_address(ec, type, ECARD_SYNC)) == NULL) goto nodev; cid.r_zero = 1; @@ -1019,7 +1013,7 @@ ecard_probe(int slot, card_type_t type) ec->cid.fiqmask = cid.r_fiqmask; ec->cid.fiqoff = ecard_gets24(cid.r_fiqoff); ec->fiqaddr = - ec->irqaddr = (void __iomem *)ioaddr(ec->podaddr); + ec->irqaddr = addr; if (ec->cid.is) { ec->irqmask = ec->cid.irqmask; @@ -1048,10 +1042,8 @@ ecard_probe(int slot, card_type_t type) set_irq_flags(ec->irq, IRQF_VALID); } -#ifdef IO_EC_MEMC8_BASE if (slot == 8) ec->irq = 11; -#endif #ifdef CONFIG_ARCH_RPC /* On RiscPC, only first two slots have DMA capability */ if (slot < 2) @@ -1097,9 +1089,7 @@ static int __init ecard_init(void) ecard_probe(slot, ECARD_IOC); } -#ifdef IO_EC_MEMC8_BASE ecard_probe(8, ECARD_IOC); -#endif irqhw = ecard_probeirqhw(); diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index a87cbf889ff479f635df3d42af731f80e32e8e64..9ad50c4208aebf5aaf7ee245444da5789935b269 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -24,6 +24,7 @@ #include #include #include +#include #include "entry-header.S" #include @@ -262,8 +263,7 @@ __und_svc: ldr r0, [r4, #-4] #else ldrh r0, [r4, #-2] @ Thumb instruction at LR - 2 - and r9, r0, #0xf800 - cmp r9, #0xe800 @ 32-bit instruction if xx >= 0 + cmp r0, #0xe800 @ 32-bit instruction if xx >= 0 ldrhhs r9, [r4] @ bottom 16 bits orrhs r0, r9, r0, lsl #16 #endif @@ -440,18 +440,46 @@ __und_usr: #endif beq call_fpe @ Thumb instruction -#if __LINUX_ARM_ARCH__ >= 7 +#if CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7 +/* + * Thumb-2 instruction handling. Note that because pre-v6 and >= v6 platforms + * can never be supported in a single kernel, this code is not applicable at + * all when __LINUX_ARM_ARCH__ < 6. This allows simplifying assumptions to be + * made about .arch directives. + */ +#if __LINUX_ARM_ARCH__ < 7 +/* If the target CPU may not be Thumb-2-capable, a run-time check is needed: */ +#define NEED_CPU_ARCHITECTURE + ldr r5, .LCcpu_architecture + ldr r5, [r5] + cmp r5, #CPU_ARCH_ARMv7 + blo __und_usr_unknown +/* + * The following code won't get run unless the running CPU really is v7, so + * coding round the lack of ldrht on older arches is pointless. Temporarily + * override the assembler target arch with the minimum required instead: + */ + .arch armv6t2 +#endif 2: ARM( ldrht r5, [r4], #2 ) THUMB( ldrht r5, [r4] ) THUMB( add r4, r4, #2 ) - and r0, r5, #0xf800 @ mask bits 111x x... .... .... - cmp r0, #0xe800 @ 32bit instruction if xx != 0 + cmp r5, #0xe800 @ 32bit instruction if xx != 0 blo __und_usr_unknown 3: ldrht r0, [r4] add r2, r2, #2 @ r2 is PC + 2, make it PC + 4 orr r0, r0, r5, lsl #16 + +#if __LINUX_ARM_ARCH__ < 7 +/* If the target arch was overridden, change it back: */ +#ifdef CONFIG_CPU_32v6K + .arch armv6k #else + .arch armv6 +#endif +#endif /* __LINUX_ARM_ARCH__ < 7 */ +#else /* !(CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7) */ b __und_usr_unknown #endif UNWIND(.fnend ) @@ -578,6 +606,12 @@ call_fpe: movw_pc lr @ CP#14 (Debug) movw_pc lr @ CP#15 (Control) +#ifdef NEED_CPU_ARCHITECTURE + .align 2 +.LCcpu_architecture: + .word __cpu_architecture +#endif + #ifdef CONFIG_NEON .align 6 diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 742b6108a00168b8ed8c391c6d8e8b1b9c438fc6..566c54c2a1fef28bffea090e89bcec998b73ede6 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -21,6 +21,7 @@ #include #include #include +#include #ifdef CONFIG_DEBUG_LL #include @@ -38,11 +39,14 @@ #error KERNEL_RAM_VADDR must start at 0xXXXX8000 #endif +#define PG_DIR_SIZE 0x4000 +#define PMD_ORDER 2 + .globl swapper_pg_dir - .equ swapper_pg_dir, KERNEL_RAM_VADDR - 0x4000 + .equ swapper_pg_dir, KERNEL_RAM_VADDR - PG_DIR_SIZE .macro pgtbl, rd, phys - add \rd, \phys, #TEXT_OFFSET - 0x4000 + add \rd, \phys, #TEXT_OFFSET - PG_DIR_SIZE .endm #ifdef CONFIG_XIP_KERNEL @@ -95,7 +99,7 @@ ENTRY(stext) sub r4, r3, r4 @ (PHYS_OFFSET - PAGE_OFFSET) add r8, r8, r4 @ PHYS_OFFSET #else - ldr r8, =PLAT_PHYS_OFFSET + ldr r8, =PHYS_OFFSET @ always constant in this case #endif /* @@ -148,11 +152,11 @@ __create_page_tables: pgtbl r4, r8 @ page table address /* - * Clear the 16K level 1 swapper page table + * Clear the swapper page table */ mov r0, r4 mov r3, #0 - add r6, r0, #0x4000 + add r6, r0, #PG_DIR_SIZE 1: str r3, [r0], #4 str r3, [r0], #4 str r3, [r0], #4 @@ -171,30 +175,30 @@ __create_page_tables: sub r0, r0, r3 @ virt->phys offset add r5, r5, r0 @ phys __enable_mmu add r6, r6, r0 @ phys __enable_mmu_end - mov r5, r5, lsr #20 - mov r6, r6, lsr #20 + mov r5, r5, lsr #SECTION_SHIFT + mov r6, r6, lsr #SECTION_SHIFT -1: orr r3, r7, r5, lsl #20 @ flags + kernel base - str r3, [r4, r5, lsl #2] @ identity mapping - teq r5, r6 - addne r5, r5, #1 @ next section - bne 1b +1: orr r3, r7, r5, lsl #SECTION_SHIFT @ flags + kernel base + str r3, [r4, r5, lsl #PMD_ORDER] @ identity mapping + cmp r5, r6 + addlo r5, r5, #1 @ next section + blo 1b /* * Now setup the pagetables for our kernel direct * mapped region. */ mov r3, pc - mov r3, r3, lsr #20 - orr r3, r7, r3, lsl #20 - add r0, r4, #(KERNEL_START & 0xff000000) >> 18 - str r3, [r0, #(KERNEL_START & 0x00f00000) >> 18]! + mov r3, r3, lsr #SECTION_SHIFT + orr r3, r7, r3, lsl #SECTION_SHIFT + add r0, r4, #(KERNEL_START & 0xff000000) >> (SECTION_SHIFT - PMD_ORDER) + str r3, [r0, #((KERNEL_START & 0x00f00000) >> SECTION_SHIFT) << PMD_ORDER]! ldr r6, =(KERNEL_END - 1) - add r0, r0, #4 - add r6, r4, r6, lsr #18 + add r0, r0, #1 << PMD_ORDER + add r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER) 1: cmp r0, r6 - add r3, r3, #1 << 20 - strls r3, [r0], #4 + add r3, r3, #1 << SECTION_SHIFT + strls r3, [r0], #1 << PMD_ORDER bls 1b #ifdef CONFIG_XIP_KERNEL @@ -203,11 +207,11 @@ __create_page_tables: */ add r3, r8, #TEXT_OFFSET orr r3, r3, r7 - add r0, r4, #(KERNEL_RAM_VADDR & 0xff000000) >> 18 - str r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> 18]! + add r0, r4, #(KERNEL_RAM_VADDR & 0xff000000) >> (SECTION_SHIFT - PMD_ORDER) + str r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> (SECTION_SHIFT - PMD_ORDER)]! ldr r6, =(_end - 1) add r0, r0, #4 - add r6, r4, r6, lsr #18 + add r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER) 1: cmp r0, r6 add r3, r3, #1 << 20 strls r3, [r0], #4 @@ -218,12 +222,12 @@ __create_page_tables: * Then map boot params address in r2 or * the first 1MB of ram if boot params address is not specified. */ - mov r0, r2, lsr #20 - movs r0, r0, lsl #20 + mov r0, r2, lsr #SECTION_SHIFT + movs r0, r0, lsl #SECTION_SHIFT moveq r0, r8 sub r3, r0, r8 add r3, r3, #PAGE_OFFSET - add r3, r4, r3, lsr #18 + add r3, r4, r3, lsr #(SECTION_SHIFT - PMD_ORDER) orr r6, r7, r0 str r6, [r3] @@ -234,23 +238,23 @@ __create_page_tables: * This allows debug messages to be output * via a serial console before paging_init. */ - addruart r7, r3 + addruart r7, r3, r0 - mov r3, r3, lsr #20 - mov r3, r3, lsl #2 + mov r3, r3, lsr #SECTION_SHIFT + mov r3, r3, lsl #PMD_ORDER add r0, r4, r3 rsb r3, r3, #0x4000 @ PTRS_PER_PGD*sizeof(long) cmp r3, #0x0800 @ limit to 512MB movhi r3, #0x0800 add r6, r0, r3 - mov r3, r7, lsr #20 + mov r3, r7, lsr #SECTION_SHIFT ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags - orr r3, r7, r3, lsl #20 + orr r3, r7, r3, lsl #SECTION_SHIFT 1: str r3, [r0], #4 - add r3, r3, #1 << 20 - teq r0, r6 - bne 1b + add r3, r3, #1 << SECTION_SHIFT + cmp r0, r6 + blo 1b #else /* CONFIG_DEBUG_ICEDCC */ /* we don't need any serial debugging mappings for ICEDCC */ @@ -262,7 +266,7 @@ __create_page_tables: * If we're using the NetWinder or CATS, we also need to map * in the 16550-type serial port for the debug messages */ - add r0, r4, #0xff000000 >> 18 + add r0, r4, #0xff000000 >> (SECTION_SHIFT - PMD_ORDER) orr r3, r7, #0x7c000000 str r3, [r0] #endif @@ -272,10 +276,10 @@ __create_page_tables: * Similar reasons here - for debug. This is * only for Acorn RiscPC architectures. */ - add r0, r4, #0x02000000 >> 18 + add r0, r4, #0x02000000 >> (SECTION_SHIFT - PMD_ORDER) orr r3, r7, #0x02000000 str r3, [r0] - add r0, r4, #0xd8000000 >> 18 + add r0, r4, #0xd8000000 >> (SECTION_SHIFT - PMD_ORDER) str r3, [r0] #endif #endif @@ -488,13 +492,8 @@ __fixup_pv_table: add r5, r5, r3 @ adjust table end address add r7, r7, r3 @ adjust __pv_phys_offset address str r8, [r7] @ save computed PHYS_OFFSET to __pv_phys_offset -#ifndef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT mov r6, r3, lsr #24 @ constant for add/sub instructions teq r3, r6, lsl #24 @ must be 16MiB aligned -#else - mov r6, r3, lsr #16 @ constant for add/sub instructions - teq r3, r6, lsl #16 @ must be 64kiB aligned -#endif THUMB( it ne @ cross section branch ) bne __error str r6, [r7, #4] @ save to __pv_offset @@ -510,20 +509,8 @@ ENDPROC(__fixup_pv_table) .text __fixup_a_pv_table: #ifdef CONFIG_THUMB2_KERNEL -#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT - lsls r0, r6, #24 - lsr r6, #8 - beq 1f - clz r7, r0 - lsr r0, #24 - lsl r0, r7 - bic r0, 0x0080 - lsrs r7, #1 - orrcs r0, #0x0080 - orr r0, r0, r7, lsl #12 -#endif -1: lsls r6, #24 - beq 4f + lsls r6, #24 + beq 2f clz r7, r6 lsr r6, #24 lsl r6, r7 @@ -532,43 +519,25 @@ __fixup_a_pv_table: orrcs r6, #0x0080 orr r6, r6, r7, lsl #12 orr r6, #0x4000 - b 4f -2: @ at this point the C flag is always clear - add r7, r3 -#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT - ldrh ip, [r7] - tst ip, 0x0400 @ the i bit tells us LS or MS byte - beq 3f - cmp r0, #0 @ set C flag, and ... - biceq ip, 0x0400 @ immediate zero value has a special encoding - streqh ip, [r7] @ that requires the i bit cleared -#endif -3: ldrh ip, [r7, #2] + b 2f +1: add r7, r3 + ldrh ip, [r7, #2] and ip, 0x8f00 - orrcc ip, r6 @ mask in offset bits 31-24 - orrcs ip, r0 @ mask in offset bits 23-16 + orr ip, r6 @ mask in offset bits 31-24 strh ip, [r7, #2] -4: cmp r4, r5 +2: cmp r4, r5 ldrcc r7, [r4], #4 @ use branch for delay slot - bcc 2b + bcc 1b bx lr #else -#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT - and r0, r6, #255 @ offset bits 23-16 - mov r6, r6, lsr #8 @ offset bits 31-24 -#else - mov r0, #0 @ just in case... -#endif - b 3f -2: ldr ip, [r7, r3] + b 2f +1: ldr ip, [r7, r3] bic ip, ip, #0x000000ff - tst ip, #0x400 @ rotate shift tells us LS or MS byte - orrne ip, ip, r6 @ mask in offset bits 31-24 - orreq ip, ip, r0 @ mask in offset bits 23-16 + orr ip, ip, r6 @ mask in offset bits 31-24 str ip, [r7, r3] -3: cmp r4, r5 +2: cmp r4, r5 ldrcc r7, [r4], #4 @ use branch for delay slot - bcc 2b + bcc 1b mov pc, lr #endif ENDPROC(__fixup_a_pv_table) diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index a927ca1f5566ce67055296f9a45f9e8714dcda51..814a52a9dc39abf401629e429879080ca1e2173a 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c @@ -45,7 +45,6 @@ static DEFINE_PER_CPU(struct perf_event *, wp_on_reg[ARM_MAX_WRP]); /* Number of BRP/WRP registers on this CPU. */ static int core_num_brps; -static int core_num_reserved_brps; static int core_num_wrps; /* Debug architecture version. */ @@ -137,10 +136,11 @@ static u8 get_debug_arch(void) u32 didr; /* Do we implement the extended CPUID interface? */ - if (WARN_ONCE((((read_cpuid_id() >> 16) & 0xf) != 0xf), - "CPUID feature registers not supported. " - "Assuming v6 debug is present.\n")) + if (((read_cpuid_id() >> 16) & 0xf) != 0xf) { + pr_warning("CPUID feature registers not supported. " + "Assuming v6 debug is present.\n"); return ARM_DEBUG_ARCH_V6; + } ARM_DBG_READ(c0, 0, didr); return (didr >> 16) & 0xf; @@ -154,10 +154,21 @@ u8 arch_get_debug_arch(void) static int debug_arch_supported(void) { u8 arch = get_debug_arch(); - return arch >= ARM_DEBUG_ARCH_V6 && arch <= ARM_DEBUG_ARCH_V7_ECP14; + + /* We don't support the memory-mapped interface. */ + return (arch >= ARM_DEBUG_ARCH_V6 && arch <= ARM_DEBUG_ARCH_V7_ECP14) || + arch >= ARM_DEBUG_ARCH_V7_1; +} + +/* Determine number of WRP registers available. */ +static int get_num_wrp_resources(void) +{ + u32 didr; + ARM_DBG_READ(c0, 0, didr); + return ((didr >> 28) & 0xf) + 1; } -/* Determine number of BRP register available. */ +/* Determine number of BRP registers available. */ static int get_num_brp_resources(void) { u32 didr; @@ -176,9 +187,10 @@ static int core_has_mismatch_brps(void) static int get_num_wrps(void) { /* - * FIXME: When a watchpoint fires, the only way to work out which - * watchpoint it was is by disassembling the faulting instruction - * and working out the address of the memory access. + * On debug architectures prior to 7.1, when a watchpoint fires, the + * only way to work out which watchpoint it was is by disassembling + * the faulting instruction and working out the address of the memory + * access. * * Furthermore, we can only do this if the watchpoint was precise * since imprecise watchpoints prevent us from calculating register @@ -192,36 +204,17 @@ static int get_num_wrps(void) * [the ARM ARM states that the DFAR is UNKNOWN, but experience shows * that it is set on some implementations]. */ + if (get_debug_arch() < ARM_DEBUG_ARCH_V7_1) + return 1; -#if 0 - int wrps; - u32 didr; - ARM_DBG_READ(c0, 0, didr); - wrps = ((didr >> 28) & 0xf) + 1; -#endif - int wrps = 1; - - if (core_has_mismatch_brps() && wrps >= get_num_brp_resources()) - wrps = get_num_brp_resources() - 1; - - return wrps; -} - -/* We reserve one breakpoint for each watchpoint. */ -static int get_num_reserved_brps(void) -{ - if (core_has_mismatch_brps()) - return get_num_wrps(); - return 0; + return get_num_wrp_resources(); } /* Determine number of usable BRPs available. */ static int get_num_brps(void) { int brps = get_num_brp_resources(); - if (core_has_mismatch_brps()) - brps -= get_num_reserved_brps(); - return brps; + return core_has_mismatch_brps() ? brps - 1 : brps; } /* @@ -239,7 +232,7 @@ static int enable_monitor_mode(void) /* Ensure that halting mode is disabled. */ if (WARN_ONCE(dscr & ARM_DSCR_HDBGEN, - "halting debug mode enabled. Unable to access hardware resources.\n")) { + "halting debug mode enabled. Unable to access hardware resources.\n")) { ret = -EPERM; goto out; } @@ -255,6 +248,7 @@ static int enable_monitor_mode(void) ARM_DBG_WRITE(c1, 0, (dscr | ARM_DSCR_MDBGEN)); break; case ARM_DEBUG_ARCH_V7_ECP14: + case ARM_DEBUG_ARCH_V7_1: ARM_DBG_WRITE(c2, 2, (dscr | ARM_DSCR_MDBGEN)); break; default: @@ -346,24 +340,10 @@ int arch_install_hw_breakpoint(struct perf_event *bp) val_base = ARM_BASE_BVR; slots = (struct perf_event **)__get_cpu_var(bp_on_reg); max_slots = core_num_brps; - if (info->step_ctrl.enabled) { - /* Override the breakpoint data with the step data. */ - addr = info->trigger & ~0x3; - ctrl = encode_ctrl_reg(info->step_ctrl); - } } else { /* Watchpoint */ - if (info->step_ctrl.enabled) { - /* Install into the reserved breakpoint region. */ - ctrl_base = ARM_BASE_BCR + core_num_brps; - val_base = ARM_BASE_BVR + core_num_brps; - /* Override the watchpoint data with the step data. */ - addr = info->trigger & ~0x3; - ctrl = encode_ctrl_reg(info->step_ctrl); - } else { - ctrl_base = ARM_BASE_WCR; - val_base = ARM_BASE_WVR; - } + ctrl_base = ARM_BASE_WCR; + val_base = ARM_BASE_WVR; slots = (struct perf_event **)__get_cpu_var(wp_on_reg); max_slots = core_num_wrps; } @@ -382,6 +362,17 @@ int arch_install_hw_breakpoint(struct perf_event *bp) goto out; } + /* Override the breakpoint data with the step data. */ + if (info->step_ctrl.enabled) { + addr = info->trigger & ~0x3; + ctrl = encode_ctrl_reg(info->step_ctrl); + if (info->ctrl.type != ARM_BREAKPOINT_EXECUTE) { + i = 0; + ctrl_base = ARM_BASE_BCR + core_num_brps; + val_base = ARM_BASE_BVR + core_num_brps; + } + } + /* Setup the address register. */ write_wb_reg(val_base + i, addr); @@ -405,10 +396,7 @@ void arch_uninstall_hw_breakpoint(struct perf_event *bp) max_slots = core_num_brps; } else { /* Watchpoint */ - if (info->step_ctrl.enabled) - base = ARM_BASE_BCR + core_num_brps; - else - base = ARM_BASE_WCR; + base = ARM_BASE_WCR; slots = (struct perf_event **)__get_cpu_var(wp_on_reg); max_slots = core_num_wrps; } @@ -426,6 +414,13 @@ void arch_uninstall_hw_breakpoint(struct perf_event *bp) if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot\n")) return; + /* Ensure that we disable the mismatch breakpoint. */ + if (info->ctrl.type != ARM_BREAKPOINT_EXECUTE && + info->step_ctrl.enabled) { + i = 0; + base = ARM_BASE_BCR + core_num_brps; + } + /* Reset the control register. */ write_wb_reg(base + i, 0); } @@ -632,10 +627,9 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) * we can use the mismatch feature as a poor-man's hardware * single-step, but this only works for per-task breakpoints. */ - if (WARN_ONCE(!bp->overflow_handler && - (arch_check_bp_in_kernelspace(bp) || !core_has_mismatch_brps() - || !bp->hw.bp_target), - "overflow handler required but none found\n")) { + if (!bp->overflow_handler && (arch_check_bp_in_kernelspace(bp) || + !core_has_mismatch_brps() || !bp->hw.bp_target)) { + pr_warning("overflow handler required but none found\n"); ret = -EINVAL; } out: @@ -666,34 +660,62 @@ static void disable_single_step(struct perf_event *bp) arch_install_hw_breakpoint(bp); } -static void watchpoint_handler(unsigned long unknown, struct pt_regs *regs) +static void watchpoint_handler(unsigned long addr, unsigned int fsr, + struct pt_regs *regs) { - int i; + int i, access; + u32 val, ctrl_reg, alignment_mask; struct perf_event *wp, **slots; struct arch_hw_breakpoint *info; + struct arch_hw_breakpoint_ctrl ctrl; slots = (struct perf_event **)__get_cpu_var(wp_on_reg); - /* Without a disassembler, we can only handle 1 watchpoint. */ - BUG_ON(core_num_wrps > 1); - for (i = 0; i < core_num_wrps; ++i) { rcu_read_lock(); wp = slots[i]; - if (wp == NULL) { - rcu_read_unlock(); - continue; - } + if (wp == NULL) + goto unlock; + info = counter_arch_bp(wp); /* - * The DFAR is an unknown value. Since we only allow a - * single watchpoint, we can set the trigger to the lowest - * possible faulting address. + * The DFAR is an unknown value on debug architectures prior + * to 7.1. Since we only allow a single watchpoint on these + * older CPUs, we can set the trigger to the lowest possible + * faulting address. */ - info = counter_arch_bp(wp); - info->trigger = wp->attr.bp_addr; + if (debug_arch < ARM_DEBUG_ARCH_V7_1) { + BUG_ON(i > 0); + info->trigger = wp->attr.bp_addr; + } else { + if (info->ctrl.len == ARM_BREAKPOINT_LEN_8) + alignment_mask = 0x7; + else + alignment_mask = 0x3; + + /* Check if the watchpoint value matches. */ + val = read_wb_reg(ARM_BASE_WVR + i); + if (val != (addr & ~alignment_mask)) + goto unlock; + + /* Possible match, check the byte address select. */ + ctrl_reg = read_wb_reg(ARM_BASE_WCR + i); + decode_ctrl_reg(ctrl_reg, &ctrl); + if (!((1 << (addr & alignment_mask)) & ctrl.len)) + goto unlock; + + /* Check that the access type matches. */ + access = (fsr & ARM_FSR_ACCESS_MASK) ? HW_BREAKPOINT_W : + HW_BREAKPOINT_R; + if (!(access & hw_breakpoint_type(wp))) + goto unlock; + + /* We have a winner. */ + info->trigger = addr; + } + pr_debug("watchpoint fired: address = 0x%x\n", info->trigger); perf_bp_event(wp, regs); @@ -705,6 +727,7 @@ static void watchpoint_handler(unsigned long unknown, struct pt_regs *regs) if (!wp->overflow_handler) enable_single_step(wp, instruction_pointer(regs)); +unlock: rcu_read_unlock(); } } @@ -717,7 +740,7 @@ static void watchpoint_single_step_handler(unsigned long pc) slots = (struct perf_event **)__get_cpu_var(wp_on_reg); - for (i = 0; i < core_num_reserved_brps; ++i) { + for (i = 0; i < core_num_wrps; ++i) { rcu_read_lock(); wp = slots[i]; @@ -820,7 +843,7 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr, case ARM_ENTRY_ASYNC_WATCHPOINT: WARN(1, "Asynchronous watchpoint exception taken. Debugging results may be unreliable\n"); case ARM_ENTRY_SYNC_WATCHPOINT: - watchpoint_handler(addr, regs); + watchpoint_handler(addr, fsr, regs); break; default: ret = 1; /* Unhandled fault. */ @@ -834,11 +857,31 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr, /* * One-time initialisation. */ -static void reset_ctrl_regs(void *info) +static cpumask_t debug_err_mask; + +static int debug_reg_trap(struct pt_regs *regs, unsigned int instr) { - int i, cpu = smp_processor_id(); + int cpu = smp_processor_id(); + + pr_warning("Debug register access (0x%x) caused undefined instruction on CPU %d\n", + instr, cpu); + + /* Set the error flag for this CPU and skip the faulting instruction. */ + cpumask_set_cpu(cpu, &debug_err_mask); + instruction_pointer(regs) += 4; + return 0; +} + +static struct undef_hook debug_reg_hook = { + .instr_mask = 0x0fe80f10, + .instr_val = 0x0e000e10, + .fn = debug_reg_trap, +}; + +static void reset_ctrl_regs(void *unused) +{ + int i, raw_num_brps, err = 0, cpu = smp_processor_id(); u32 dbg_power; - cpumask_t *cpumask = info; /* * v7 debug contains save and restore registers so that debug state @@ -848,38 +891,57 @@ static void reset_ctrl_regs(void *info) * Access Register to avoid taking undefined instruction exceptions * later on. */ - if (debug_arch >= ARM_DEBUG_ARCH_V7_ECP14) { + switch (debug_arch) { + case ARM_DEBUG_ARCH_V6: + case ARM_DEBUG_ARCH_V6_1: + /* ARMv6 cores just need to reset the registers. */ + goto reset_regs; + case ARM_DEBUG_ARCH_V7_ECP14: /* * Ensure sticky power-down is clear (i.e. debug logic is * powered up). */ asm volatile("mrc p14, 0, %0, c1, c5, 4" : "=r" (dbg_power)); - if ((dbg_power & 0x1) == 0) { - pr_warning("CPU %d debug is powered down!\n", cpu); - cpumask_or(cpumask, cpumask, cpumask_of(cpu)); - return; - } - + if ((dbg_power & 0x1) == 0) + err = -EPERM; + break; + case ARM_DEBUG_ARCH_V7_1: /* - * Unconditionally clear the lock by writing a value - * other than 0xC5ACCE55 to the access register. + * Ensure the OS double lock is clear. */ - asm volatile("mcr p14, 0, %0, c1, c0, 4" : : "r" (0)); - isb(); + asm volatile("mrc p14, 0, %0, c1, c3, 4" : "=r" (dbg_power)); + if ((dbg_power & 0x1) == 1) + err = -EPERM; + break; + } - /* - * Clear any configured vector-catch events before - * enabling monitor mode. - */ - asm volatile("mcr p14, 0, %0, c0, c7, 0" : : "r" (0)); - isb(); + if (err) { + pr_warning("CPU %d debug is powered down!\n", cpu); + cpumask_or(&debug_err_mask, &debug_err_mask, cpumask_of(cpu)); + return; } + /* + * Unconditionally clear the lock by writing a value + * other than 0xC5ACCE55 to the access register. + */ + asm volatile("mcr p14, 0, %0, c1, c0, 4" : : "r" (0)); + isb(); + + /* + * Clear any configured vector-catch events before + * enabling monitor mode. + */ + asm volatile("mcr p14, 0, %0, c0, c7, 0" : : "r" (0)); + isb(); + +reset_regs: if (enable_monitor_mode()) return; /* We must also reset any reserved registers. */ - for (i = 0; i < core_num_brps + core_num_reserved_brps; ++i) { + raw_num_brps = get_num_brp_resources(); + for (i = 0; i < raw_num_brps; ++i) { write_wb_reg(ARM_BASE_BCR + i, 0UL); write_wb_reg(ARM_BASE_BVR + i, 0UL); } @@ -895,6 +957,7 @@ static int __cpuinit dbg_reset_notify(struct notifier_block *self, { if (action == CPU_ONLINE) smp_call_function_single((int)cpu, reset_ctrl_regs, NULL, 1); + return NOTIFY_OK; } @@ -905,7 +968,6 @@ static struct notifier_block __cpuinitdata dbg_reset_nb = { static int __init arch_hw_breakpoint_init(void) { u32 dscr; - cpumask_t cpumask = { CPU_BITS_NONE }; debug_arch = get_debug_arch(); @@ -916,28 +978,31 @@ static int __init arch_hw_breakpoint_init(void) /* Determine how many BRPs/WRPs are available. */ core_num_brps = get_num_brps(); - core_num_reserved_brps = get_num_reserved_brps(); core_num_wrps = get_num_wrps(); - pr_info("found %d breakpoint and %d watchpoint registers.\n", - core_num_brps + core_num_reserved_brps, core_num_wrps); - - if (core_num_reserved_brps) - pr_info("%d breakpoint(s) reserved for watchpoint " - "single-step.\n", core_num_reserved_brps); + /* + * We need to tread carefully here because DBGSWENABLE may be + * driven low on this core and there isn't an architected way to + * determine that. + */ + register_undef_hook(&debug_reg_hook); /* * Reset the breakpoint resources. We assume that a halting * debugger will leave the world in a nice state for us. */ - on_each_cpu(reset_ctrl_regs, &cpumask, 1); - if (!cpumask_empty(&cpumask)) { + on_each_cpu(reset_ctrl_regs, NULL, 1); + unregister_undef_hook(&debug_reg_hook); + if (!cpumask_empty(&debug_err_mask)) { core_num_brps = 0; - core_num_reserved_brps = 0; core_num_wrps = 0; return 0; } + pr_info("found %d " "%s" "breakpoint and %d watchpoint registers.\n", + core_num_brps, core_has_mismatch_brps() ? "(+1 reserved) " : + "", core_num_wrps); + ARM_DBG_READ(c1, 0, dscr); if (dscr & ARM_DSCR_HDBGEN) { max_watchpoint_len = 4; diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index de3dcab8610bbbf6776d1406e3cb90cdb85d574f..7cb29261249af0c74157fd362d15827723ee1715 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -35,8 +35,8 @@ #include #include #include -#include +#include #include #include #include @@ -58,9 +58,6 @@ int arch_show_interrupts(struct seq_file *p, int prec) #endif #ifdef CONFIG_SMP show_ipi_list(p, prec); -#endif -#ifdef CONFIG_LOCAL_TIMERS - show_local_irqs(p, prec); #endif seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count); return 0; diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c index 79203ee1d03981d861dece803868f366ec1add98..9fe8910308af922eda3c17ffee908c99652c1a1f 100644 --- a/arch/arm/kernel/kprobes-arm.c +++ b/arch/arm/kernel/kprobes-arm.c @@ -60,6 +60,7 @@ #include #include +#include #include "kprobes.h" @@ -971,6 +972,9 @@ const union decode_item kprobe_decode_arm_table[] = { DECODE_END }; +#ifdef CONFIG_ARM_KPROBES_TEST_MODULE +EXPORT_SYMBOL_GPL(kprobe_decode_arm_table); +#endif static void __kprobes arm_singlestep(struct kprobe *p, struct pt_regs *regs) { diff --git a/arch/arm/kernel/kprobes-test-arm.c b/arch/arm/kernel/kprobes-test-arm.c new file mode 100644 index 0000000000000000000000000000000000000000..fc82de8bdcce1081801cece62fa3d97480d520e1 --- /dev/null +++ b/arch/arm/kernel/kprobes-test-arm.c @@ -0,0 +1,1323 @@ +/* + * arch/arm/kernel/kprobes-test-arm.c + * + * Copyright (C) 2011 Jon Medhurst . + * + * 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 +#include + +#include "kprobes-test.h" + + +#define TEST_ISA "32" + +#define TEST_ARM_TO_THUMB_INTERWORK_R(code1, reg, val, code2) \ + TESTCASE_START(code1 #reg code2) \ + TEST_ARG_REG(reg, val) \ + TEST_ARG_REG(14, 99f) \ + TEST_ARG_END("") \ + "50: nop \n\t" \ + "1: "code1 #reg code2" \n\t" \ + " bx lr \n\t" \ + ".thumb \n\t" \ + "3: adr lr, 2f \n\t" \ + " bx lr \n\t" \ + ".arm \n\t" \ + "2: nop \n\t" \ + TESTCASE_END + +#define TEST_ARM_TO_THUMB_INTERWORK_P(code1, reg, val, code2) \ + TESTCASE_START(code1 #reg code2) \ + TEST_ARG_PTR(reg, val) \ + TEST_ARG_REG(14, 99f) \ + TEST_ARG_MEM(15, 3f+1) \ + TEST_ARG_END("") \ + "50: nop \n\t" \ + "1: "code1 #reg code2" \n\t" \ + " bx lr \n\t" \ + ".thumb \n\t" \ + "3: adr lr, 2f \n\t" \ + " bx lr \n\t" \ + ".arm \n\t" \ + "2: nop \n\t" \ + TESTCASE_END + + +void kprobe_arm_test_cases(void) +{ + kprobe_test_flags = 0; + + TEST_GROUP("Data-processing (register), (register-shifted register), (immediate)") + +#define _DATA_PROCESSING_DNM(op,s,val) \ + TEST_RR( op "eq" s " r0, r",1, VAL1,", r",2, val, "") \ + TEST_RR( op "ne" s " r1, r",1, VAL1,", r",2, val, ", lsl #3") \ + TEST_RR( op "cs" s " r2, r",3, VAL1,", r",2, val, ", lsr #4") \ + TEST_RR( op "cc" s " r3, r",3, VAL1,", r",2, val, ", asr #5") \ + TEST_RR( op "mi" s " r4, r",5, VAL1,", r",2, N(val),", asr #6") \ + TEST_RR( op "pl" s " r5, r",5, VAL1,", r",2, val, ", ror #7") \ + TEST_RR( op "vs" s " r6, r",7, VAL1,", r",2, val, ", rrx") \ + TEST_R( op "vc" s " r6, r",7, VAL1,", pc, lsl #3") \ + TEST_R( op "vc" s " r6, r",7, VAL1,", sp, lsr #4") \ + TEST_R( op "vc" s " r6, pc, r",7, VAL1,", asr #5") \ + TEST_R( op "vc" s " r6, sp, r",7, VAL1,", ror #6") \ + TEST_RRR( op "hi" s " r8, r",9, VAL1,", r",14,val, ", lsl r",0, 3,"")\ + TEST_RRR( op "ls" s " r9, r",9, VAL1,", r",14,val, ", lsr r",7, 4,"")\ + TEST_RRR( op "ge" s " r10, r",11,VAL1,", r",14,val, ", asr r",7, 5,"")\ + TEST_RRR( op "lt" s " r11, r",11,VAL1,", r",14,N(val),", asr r",7, 6,"")\ + TEST_RR( op "gt" s " r12, r13" ", r",14,val, ", ror r",14,7,"")\ + TEST_RR( op "le" s " r14, r",0, val, ", r13" ", lsl r",14,8,"")\ + TEST_RR( op s " r12, pc" ", r",14,val, ", ror r",14,7,"")\ + TEST_RR( op s " r14, r",0, val, ", pc" ", lsl r",14,8,"")\ + TEST_R( op "eq" s " r0, r",11,VAL1,", #0xf5") \ + TEST_R( op "ne" s " r11, r",0, VAL1,", #0xf5000000") \ + TEST_R( op s " r7, r",8, VAL2,", #0x000af000") \ + TEST( op s " r4, pc" ", #0x00005a00") + +#define DATA_PROCESSING_DNM(op,val) \ + _DATA_PROCESSING_DNM(op,"",val) \ + _DATA_PROCESSING_DNM(op,"s",val) + +#define DATA_PROCESSING_NM(op,val) \ + TEST_RR( op "ne r",1, VAL1,", r",2, val, "") \ + TEST_RR( op "eq r",1, VAL1,", r",2, val, ", lsl #3") \ + TEST_RR( op "cc r",3, VAL1,", r",2, val, ", lsr #4") \ + TEST_RR( op "cs r",3, VAL1,", r",2, val, ", asr #5") \ + TEST_RR( op "pl r",5, VAL1,", r",2, N(val),", asr #6") \ + TEST_RR( op "mi r",5, VAL1,", r",2, val, ", ror #7") \ + TEST_RR( op "vc r",7, VAL1,", r",2, val, ", rrx") \ + TEST_R ( op "vs r",7, VAL1,", pc, lsl #3") \ + TEST_R ( op "vs r",7, VAL1,", sp, lsr #4") \ + TEST_R( op "vs pc, r",7, VAL1,", asr #5") \ + TEST_R( op "vs sp, r",7, VAL1,", ror #6") \ + TEST_RRR( op "ls r",9, VAL1,", r",14,val, ", lsl r",0, 3,"") \ + TEST_RRR( op "hi r",9, VAL1,", r",14,val, ", lsr r",7, 4,"") \ + TEST_RRR( op "lt r",11,VAL1,", r",14,val, ", asr r",7, 5,"") \ + TEST_RRR( op "ge r",11,VAL1,", r",14,N(val),", asr r",7, 6,"") \ + TEST_RR( op "le r13" ", r",14,val, ", ror r",14,7,"") \ + TEST_RR( op "gt r",0, val, ", r13" ", lsl r",14,8,"") \ + TEST_RR( op " pc" ", r",14,val, ", ror r",14,7,"") \ + TEST_RR( op " r",0, val, ", pc" ", lsl r",14,8,"") \ + TEST_R( op "eq r",11,VAL1,", #0xf5") \ + TEST_R( op "ne r",0, VAL1,", #0xf5000000") \ + TEST_R( op " r",8, VAL2,", #0x000af000") + +#define _DATA_PROCESSING_DM(op,s,val) \ + TEST_R( op "eq" s " r0, r",1, val, "") \ + TEST_R( op "ne" s " r1, r",1, val, ", lsl #3") \ + TEST_R( op "cs" s " r2, r",3, val, ", lsr #4") \ + TEST_R( op "cc" s " r3, r",3, val, ", asr #5") \ + TEST_R( op "mi" s " r4, r",5, N(val),", asr #6") \ + TEST_R( op "pl" s " r5, r",5, val, ", ror #7") \ + TEST_R( op "vs" s " r6, r",10,val, ", rrx") \ + TEST( op "vs" s " r7, pc, lsl #3") \ + TEST( op "vs" s " r7, sp, lsr #4") \ + TEST_RR( op "vc" s " r8, r",7, val, ", lsl r",0, 3,"") \ + TEST_RR( op "hi" s " r9, r",9, val, ", lsr r",7, 4,"") \ + TEST_RR( op "ls" s " r10, r",9, val, ", asr r",7, 5,"") \ + TEST_RR( op "ge" s " r11, r",11,N(val),", asr r",7, 6,"") \ + TEST_RR( op "lt" s " r12, r",11,val, ", ror r",14,7,"") \ + TEST_R( op "gt" s " r14, r13" ", lsl r",14,8,"") \ + TEST_R( op "le" s " r14, pc" ", lsl r",14,8,"") \ + TEST( op "eq" s " r0, #0xf5") \ + TEST( op "ne" s " r11, #0xf5000000") \ + TEST( op s " r7, #0x000af000") \ + TEST( op s " r4, #0x00005a00") + +#define DATA_PROCESSING_DM(op,val) \ + _DATA_PROCESSING_DM(op,"",val) \ + _DATA_PROCESSING_DM(op,"s",val) + + DATA_PROCESSING_DNM("and",0xf00f00ff) + DATA_PROCESSING_DNM("eor",0xf00f00ff) + DATA_PROCESSING_DNM("sub",VAL2) + DATA_PROCESSING_DNM("rsb",VAL2) + DATA_PROCESSING_DNM("add",VAL2) + DATA_PROCESSING_DNM("adc",VAL2) + DATA_PROCESSING_DNM("sbc",VAL2) + DATA_PROCESSING_DNM("rsc",VAL2) + DATA_PROCESSING_NM("tst",0xf00f00ff) + DATA_PROCESSING_NM("teq",0xf00f00ff) + DATA_PROCESSING_NM("cmp",VAL2) + DATA_PROCESSING_NM("cmn",VAL2) + DATA_PROCESSING_DNM("orr",0xf00f00ff) + DATA_PROCESSING_DM("mov",VAL2) + DATA_PROCESSING_DNM("bic",0xf00f00ff) + DATA_PROCESSING_DM("mvn",VAL2) + + TEST("mov ip, sp") /* This has special case emulation code */ + + TEST_SUPPORTED("mov pc, #0x1000"); + TEST_SUPPORTED("mov sp, #0x1000"); + TEST_SUPPORTED("cmp pc, #0x1000"); + TEST_SUPPORTED("cmp sp, #0x1000"); + + /* Data-processing with PC as shift*/ + TEST_UNSUPPORTED(".word 0xe15c0f1e @ cmp r12, r14, asl pc") + TEST_UNSUPPORTED(".word 0xe1a0cf1e @ mov r12, r14, asl pc") + TEST_UNSUPPORTED(".word 0xe08caf1e @ add r10, r12, r14, asl pc") + + /* Data-processing with PC as shift*/ + TEST_UNSUPPORTED("movs pc, r1") + TEST_UNSUPPORTED("movs pc, r1, lsl r2") + TEST_UNSUPPORTED("movs pc, #0x10000") + TEST_UNSUPPORTED("adds pc, lr, r1") + TEST_UNSUPPORTED("adds pc, lr, r1, lsl r2") + TEST_UNSUPPORTED("adds pc, lr, #4") + + /* Data-processing with SP as target */ + TEST("add sp, sp, #16") + TEST("sub sp, sp, #8") + TEST("bic sp, sp, #0x20") + TEST("orr sp, sp, #0x20") + TEST_PR( "add sp, r",10,0,", r",11,4,"") + TEST_PRR("add sp, r",10,0,", r",11,4,", asl r",12,1,"") + TEST_P( "mov sp, r",10,0,"") + TEST_PR( "mov sp, r",10,0,", asl r",12,0,"") + + /* Data-processing with PC as target */ + TEST_BF( "add pc, pc, #2f-1b-8") + TEST_BF_R ("add pc, pc, r",14,2f-1f-8,"") + TEST_BF_R ("add pc, r",14,2f-1f-8,", pc") + TEST_BF_R ("mov pc, r",0,2f,"") + TEST_BF_RR("mov pc, r",0,2f,", asl r",1,0,"") + TEST_BB( "sub pc, pc, #1b-2b+8") +#if __LINUX_ARM_ARCH__ >= 6 + TEST_BB( "sub pc, pc, #1b-2b+8-2") /* UNPREDICTABLE before ARMv6 */ +#endif + TEST_BB_R( "sub pc, pc, r",14, 1f-2f+8,"") + TEST_BB_R( "rsb pc, r",14,1f-2f+8,", pc") + TEST_RR( "add pc, pc, r",10,-2,", asl r",11,1,"") +#ifdef CONFIG_THUMB2_KERNEL + TEST_ARM_TO_THUMB_INTERWORK_R("add pc, pc, r",0,3f-1f-8+1,"") + TEST_ARM_TO_THUMB_INTERWORK_R("sub pc, r",0,3f+8+1,", #8") +#endif + TEST_GROUP("Miscellaneous instructions") + + TEST("mrs r0, cpsr") + TEST("mrspl r7, cpsr") + TEST("mrs r14, cpsr") + TEST_UNSUPPORTED(".word 0xe10ff000 @ mrs r15, cpsr") + TEST_UNSUPPORTED("mrs r0, spsr") + TEST_UNSUPPORTED("mrs lr, spsr") + + TEST_UNSUPPORTED("msr cpsr, r0") + TEST_UNSUPPORTED("msr cpsr_f, lr") + TEST_UNSUPPORTED("msr spsr, r0") + + TEST_BF_R("bx r",0,2f,"") + TEST_BB_R("bx r",7,2f,"") + TEST_BF_R("bxeq r",14,2f,"") + + TEST_R("clz r0, r",0, 0x0,"") + TEST_R("clzeq r7, r",14,0x1,"") + TEST_R("clz lr, r",7, 0xffffffff,"") + TEST( "clz r4, sp") + TEST_UNSUPPORTED(".word 0x016fff10 @ clz pc, r0") + TEST_UNSUPPORTED(".word 0x016f0f1f @ clz r0, pc") + +#if __LINUX_ARM_ARCH__ >= 6 + TEST_UNSUPPORTED("bxj r0") +#endif + + TEST_BF_R("blx r",0,2f,"") + TEST_BB_R("blx r",7,2f,"") + TEST_BF_R("blxeq r",14,2f,"") + TEST_UNSUPPORTED(".word 0x0120003f @ blx pc") + + TEST_RR( "qadd r0, r",1, VAL1,", r",2, VAL2,"") + TEST_RR( "qaddvs lr, r",9, VAL2,", r",8, VAL1,"") + TEST_R( "qadd lr, r",9, VAL2,", r13") + TEST_RR( "qsub r0, r",1, VAL1,", r",2, VAL2,"") + TEST_RR( "qsubvs lr, r",9, VAL2,", r",8, VAL1,"") + TEST_R( "qsub lr, r",9, VAL2,", r13") + TEST_RR( "qdadd r0, r",1, VAL1,", r",2, VAL2,"") + TEST_RR( "qdaddvs lr, r",9, VAL2,", r",8, VAL1,"") + TEST_R( "qdadd lr, r",9, VAL2,", r13") + TEST_RR( "qdsub r0, r",1, VAL1,", r",2, VAL2,"") + TEST_RR( "qdsubvs lr, r",9, VAL2,", r",8, VAL1,"") + TEST_R( "qdsub lr, r",9, VAL2,", r13") + TEST_UNSUPPORTED(".word 0xe101f050 @ qadd pc, r0, r1") + TEST_UNSUPPORTED(".word 0xe121f050 @ qsub pc, r0, r1") + TEST_UNSUPPORTED(".word 0xe141f050 @ qdadd pc, r0, r1") + TEST_UNSUPPORTED(".word 0xe161f050 @ qdsub pc, r0, r1") + TEST_UNSUPPORTED(".word 0xe16f2050 @ qdsub r2, r0, pc") + TEST_UNSUPPORTED(".word 0xe161205f @ qdsub r2, pc, r1") + + TEST_UNSUPPORTED("bkpt 0xffff") + TEST_UNSUPPORTED("bkpt 0x0000") + + TEST_UNSUPPORTED(".word 0xe1600070 @ smc #0") + + TEST_GROUP("Halfword multiply and multiply-accumulate") + + TEST_RRR( "smlabb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") + TEST_RRR( "smlabbge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") + TEST_RR( "smlabb lr, r",1, VAL2,", r",2, VAL3,", r13") + TEST_UNSUPPORTED(".word 0xe10f3281 @ smlabb pc, r1, r2, r3") + TEST_RRR( "smlatb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") + TEST_RRR( "smlatbge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") + TEST_RR( "smlatb lr, r",1, VAL2,", r",2, VAL3,", r13") + TEST_UNSUPPORTED(".word 0xe10f32a1 @ smlatb pc, r1, r2, r3") + TEST_RRR( "smlabt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") + TEST_RRR( "smlabtge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") + TEST_RR( "smlabt lr, r",1, VAL2,", r",2, VAL3,", r13") + TEST_UNSUPPORTED(".word 0xe10f32c1 @ smlabt pc, r1, r2, r3") + TEST_RRR( "smlatt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") + TEST_RRR( "smlattge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") + TEST_RR( "smlatt lr, r",1, VAL2,", r",2, VAL3,", r13") + TEST_UNSUPPORTED(".word 0xe10f32e1 @ smlatt pc, r1, r2, r3") + + TEST_RRR( "smlawb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") + TEST_RRR( "smlawbge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") + TEST_RR( "smlawb lr, r",1, VAL2,", r",2, VAL3,", r13") + TEST_UNSUPPORTED(".word 0xe12f3281 @ smlawb pc, r1, r2, r3") + TEST_RRR( "smlawt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") + TEST_RRR( "smlawtge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") + TEST_RR( "smlawt lr, r",1, VAL2,", r",2, VAL3,", r13") + TEST_UNSUPPORTED(".word 0xe12f32c1 @ smlawt pc, r1, r2, r3") + TEST_UNSUPPORTED(".word 0xe12032cf @ smlawt r0, pc, r2, r3") + TEST_UNSUPPORTED(".word 0xe1203fc1 @ smlawt r0, r1, pc, r3") + TEST_UNSUPPORTED(".word 0xe120f2c1 @ smlawt r0, r1, r2, pc") + + TEST_RR( "smulwb r0, r",1, VAL1,", r",2, VAL2,"") + TEST_RR( "smulwbge r7, r",8, VAL3,", r",9, VAL1,"") + TEST_R( "smulwb lr, r",1, VAL2,", r13") + TEST_UNSUPPORTED(".word 0xe12f02a1 @ smulwb pc, r1, r2") + TEST_RR( "smulwt r0, r",1, VAL1,", r",2, VAL2,"") + TEST_RR( "smulwtge r7, r",8, VAL3,", r",9, VAL1,"") + TEST_R( "smulwt lr, r",1, VAL2,", r13") + TEST_UNSUPPORTED(".word 0xe12f02e1 @ smulwt pc, r1, r2") + + TEST_RRRR( "smlalbb r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) + TEST_RRRR( "smlalbble r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) + TEST_RRR( "smlalbb r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13") + TEST_UNSUPPORTED(".word 0xe14f1382 @ smlalbb pc, r1, r2, r3") + TEST_UNSUPPORTED(".word 0xe141f382 @ smlalbb r1, pc, r2, r3") + TEST_RRRR( "smlaltb r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) + TEST_RRRR( "smlaltble r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) + TEST_RRR( "smlaltb r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13") + TEST_UNSUPPORTED(".word 0xe14f13a2 @ smlaltb pc, r1, r2, r3") + TEST_UNSUPPORTED(".word 0xe141f3a2 @ smlaltb r1, pc, r2, r3") + TEST_RRRR( "smlalbt r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) + TEST_RRRR( "smlalbtle r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) + TEST_RRR( "smlalbt r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13") + TEST_UNSUPPORTED(".word 0xe14f13c2 @ smlalbt pc, r1, r2, r3") + TEST_UNSUPPORTED(".word 0xe141f3c2 @ smlalbt r1, pc, r2, r3") + TEST_RRRR( "smlaltt r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) + TEST_RRRR( "smlalttle r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) + TEST_RRR( "smlaltt r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13") + TEST_UNSUPPORTED(".word 0xe14f13e2 @ smlalbb pc, r1, r2, r3") + TEST_UNSUPPORTED(".word 0xe140f3e2 @ smlalbb r0, pc, r2, r3") + TEST_UNSUPPORTED(".word 0xe14013ef @ smlalbb r0, r1, pc, r3") + TEST_UNSUPPORTED(".word 0xe1401fe2 @ smlalbb r0, r1, r2, pc") + + TEST_RR( "smulbb r0, r",1, VAL1,", r",2, VAL2,"") + TEST_RR( "smulbbge r7, r",8, VAL3,", r",9, VAL1,"") + TEST_R( "smulbb lr, r",1, VAL2,", r13") + TEST_UNSUPPORTED(".word 0xe16f0281 @ smulbb pc, r1, r2") + TEST_RR( "smultb r0, r",1, VAL1,", r",2, VAL2,"") + TEST_RR( "smultbge r7, r",8, VAL3,", r",9, VAL1,"") + TEST_R( "smultb lr, r",1, VAL2,", r13") + TEST_UNSUPPORTED(".word 0xe16f02a1 @ smultb pc, r1, r2") + TEST_RR( "smulbt r0, r",1, VAL1,", r",2, VAL2,"") + TEST_RR( "smulbtge r7, r",8, VAL3,", r",9, VAL1,"") + TEST_R( "smulbt lr, r",1, VAL2,", r13") + TEST_UNSUPPORTED(".word 0xe16f02c1 @ smultb pc, r1, r2") + TEST_RR( "smultt r0, r",1, VAL1,", r",2, VAL2,"") + TEST_RR( "smulttge r7, r",8, VAL3,", r",9, VAL1,"") + TEST_R( "smultt lr, r",1, VAL2,", r13") + TEST_UNSUPPORTED(".word 0xe16f02e1 @ smultt pc, r1, r2") + TEST_UNSUPPORTED(".word 0xe16002ef @ smultt r0, pc, r2") + TEST_UNSUPPORTED(".word 0xe1600fe1 @ smultt r0, r1, pc") + + TEST_GROUP("Multiply and multiply-accumulate") + + TEST_RR( "mul r0, r",1, VAL1,", r",2, VAL2,"") + TEST_RR( "mulls r7, r",8, VAL2,", r",9, VAL2,"") + TEST_R( "mul lr, r",4, VAL3,", r13") + TEST_UNSUPPORTED(".word 0xe00f0291 @ mul pc, r1, r2") + TEST_UNSUPPORTED(".word 0xe000029f @ mul r0, pc, r2") + TEST_UNSUPPORTED(".word 0xe0000f91 @ mul r0, r1, pc") + TEST_RR( "muls r0, r",1, VAL1,", r",2, VAL2,"") + TEST_RR( "mullss r7, r",8, VAL2,", r",9, VAL2,"") + TEST_R( "muls lr, r",4, VAL3,", r13") + TEST_UNSUPPORTED(".word 0xe01f0291 @ muls pc, r1, r2") + + TEST_RRR( "mla r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") + TEST_RRR( "mlahi r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") + TEST_RR( "mla lr, r",1, VAL2,", r",2, VAL3,", r13") + TEST_UNSUPPORTED(".word 0xe02f3291 @ mla pc, r1, r2, r3") + TEST_RRR( "mlas r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") + TEST_RRR( "mlahis r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") + TEST_RR( "mlas lr, r",1, VAL2,", r",2, VAL3,", r13") + TEST_UNSUPPORTED(".word 0xe03f3291 @ mlas pc, r1, r2, r3") + +#if __LINUX_ARM_ARCH__ >= 6 + TEST_RR( "umaal r0, r1, r",2, VAL1,", r",3, VAL2,"") + TEST_RR( "umaalls r7, r8, r",9, VAL2,", r",10, VAL1,"") + TEST_R( "umaal lr, r12, r",11,VAL3,", r13") + TEST_UNSUPPORTED(".word 0xe041f392 @ umaal pc, r1, r2, r3") + TEST_UNSUPPORTED(".word 0xe04f0392 @ umaal r0, pc, r2, r3") + TEST_UNSUPPORTED(".word 0xe0500090 @ undef") + TEST_UNSUPPORTED(".word 0xe05fff9f @ undef") + + TEST_RRR( "mls r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") + TEST_RRR( "mlshi r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") + TEST_RR( "mls lr, r",1, VAL2,", r",2, VAL3,", r13") + TEST_UNSUPPORTED(".word 0xe06f3291 @ mls pc, r1, r2, r3") + TEST_UNSUPPORTED(".word 0xe060329f @ mls r0, pc, r2, r3") + TEST_UNSUPPORTED(".word 0xe0603f91 @ mls r0, r1, pc, r3") + TEST_UNSUPPORTED(".word 0xe060f291 @ mls r0, r1, r2, pc") +#endif + + TEST_UNSUPPORTED(".word 0xe0700090 @ undef") + TEST_UNSUPPORTED(".word 0xe07fff9f @ undef") + + TEST_RR( "umull r0, r1, r",2, VAL1,", r",3, VAL2,"") + TEST_RR( "umullls r7, r8, r",9, VAL2,", r",10, VAL1,"") + TEST_R( "umull lr, r12, r",11,VAL3,", r13") + TEST_UNSUPPORTED(".word 0xe081f392 @ umull pc, r1, r2, r3") + TEST_UNSUPPORTED(".word 0xe08f1392 @ umull r1, pc, r2, r3") + TEST_RR( "umulls r0, r1, r",2, VAL1,", r",3, VAL2,"") + TEST_RR( "umulllss r7, r8, r",9, VAL2,", r",10, VAL1,"") + TEST_R( "umulls lr, r12, r",11,VAL3,", r13") + TEST_UNSUPPORTED(".word 0xe091f392 @ umulls pc, r1, r2, r3") + TEST_UNSUPPORTED(".word 0xe09f1392 @ umulls r1, pc, r2, r3") + + TEST_RRRR( "umlal r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) + TEST_RRRR( "umlalle r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) + TEST_RRR( "umlal r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13") + TEST_UNSUPPORTED(".word 0xe0af1392 @ umlal pc, r1, r2, r3") + TEST_UNSUPPORTED(".word 0xe0a1f392 @ umlal r1, pc, r2, r3") + TEST_RRRR( "umlals r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) + TEST_RRRR( "umlalles r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) + TEST_RRR( "umlals r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13") + TEST_UNSUPPORTED(".word 0xe0bf1392 @ umlals pc, r1, r2, r3") + TEST_UNSUPPORTED(".word 0xe0b1f392 @ umlals r1, pc, r2, r3") + + TEST_RR( "smull r0, r1, r",2, VAL1,", r",3, VAL2,"") + TEST_RR( "smullls r7, r8, r",9, VAL2,", r",10, VAL1,"") + TEST_R( "smull lr, r12, r",11,VAL3,", r13") + TEST_UNSUPPORTED(".word 0xe0c1f392 @ smull pc, r1, r2, r3") + TEST_UNSUPPORTED(".word 0xe0cf1392 @ smull r1, pc, r2, r3") + TEST_RR( "smulls r0, r1, r",2, VAL1,", r",3, VAL2,"") + TEST_RR( "smulllss r7, r8, r",9, VAL2,", r",10, VAL1,"") + TEST_R( "smulls lr, r12, r",11,VAL3,", r13") + TEST_UNSUPPORTED(".word 0xe0d1f392 @ smulls pc, r1, r2, r3") + TEST_UNSUPPORTED(".word 0xe0df1392 @ smulls r1, pc, r2, r3") + + TEST_RRRR( "smlal r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) + TEST_RRRR( "smlalle r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) + TEST_RRR( "smlal r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13") + TEST_UNSUPPORTED(".word 0xe0ef1392 @ smlal pc, r1, r2, r3") + TEST_UNSUPPORTED(".word 0xe0e1f392 @ smlal r1, pc, r2, r3") + TEST_RRRR( "smlals r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) + TEST_RRRR( "smlalles r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) + TEST_RRR( "smlals r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13") + TEST_UNSUPPORTED(".word 0xe0ff1392 @ smlals pc, r1, r2, r3") + TEST_UNSUPPORTED(".word 0xe0f0f392 @ smlals r0, pc, r2, r3") + TEST_UNSUPPORTED(".word 0xe0f0139f @ smlals r0, r1, pc, r3") + TEST_UNSUPPORTED(".word 0xe0f01f92 @ smlals r0, r1, r2, pc") + + TEST_GROUP("Synchronization primitives") + + /* + * Use hard coded constants for SWP instructions to avoid warnings + * about deprecated instructions. + */ + TEST_RP( ".word 0xe108e097 @ swp lr, r",7,VAL2,", [r",8,0,"]") + TEST_R( ".word 0x610d0091 @ swpvs r0, r",1,VAL1,", [sp]") + TEST_RP( ".word 0xe10cd09e @ swp sp, r",14,VAL2,", [r",12,13*4,"]") + TEST_UNSUPPORTED(".word 0xe102f091 @ swp pc, r1, [r2]") + TEST_UNSUPPORTED(".word 0xe102009f @ swp r0, pc, [r2]") + TEST_UNSUPPORTED(".word 0xe10f0091 @ swp r0, r1, [pc]") + TEST_RP( ".word 0xe148e097 @ swpb lr, r",7,VAL2,", [r",8,0,"]") + TEST_R( ".word 0x614d0091 @ swpvsb r0, r",1,VAL1,", [sp]") + TEST_UNSUPPORTED(".word 0xe142f091 @ swpb pc, r1, [r2]") + + TEST_UNSUPPORTED(".word 0xe1100090") /* Unallocated space */ + TEST_UNSUPPORTED(".word 0xe1200090") /* Unallocated space */ + TEST_UNSUPPORTED(".word 0xe1300090") /* Unallocated space */ + TEST_UNSUPPORTED(".word 0xe1500090") /* Unallocated space */ + TEST_UNSUPPORTED(".word 0xe1600090") /* Unallocated space */ + TEST_UNSUPPORTED(".word 0xe1700090") /* Unallocated space */ +#if __LINUX_ARM_ARCH__ >= 6 + TEST_UNSUPPORTED("ldrex r2, [sp]") + TEST_UNSUPPORTED("strexd r0, r2, r3, [sp]") + TEST_UNSUPPORTED("ldrexd r2, r3, [sp]") + TEST_UNSUPPORTED("strexb r0, r2, [sp]") + TEST_UNSUPPORTED("ldrexb r2, [sp]") + TEST_UNSUPPORTED("strexh r0, r2, [sp]") + TEST_UNSUPPORTED("ldrexh r2, [sp]") +#endif + TEST_GROUP("Extra load/store instructions") + + TEST_RPR( "strh r",0, VAL1,", [r",1, 48,", -r",2, 24,"]") + TEST_RPR( "streqh r",14,VAL2,", [r",13,0, ", r",12, 48,"]") + TEST_RPR( "strh r",1, VAL1,", [r",2, 24,", r",3, 48,"]!") + TEST_RPR( "strneh r",12,VAL2,", [r",11,48,", -r",10,24,"]!") + TEST_RPR( "strh r",2, VAL1,", [r",3, 24,"], r",4, 48,"") + TEST_RPR( "strh r",10,VAL2,", [r",9, 48,"], -r",11,24,"") + TEST_UNSUPPORTED(".word 0xe1afc0ba @ strh r12, [pc, r10]!") + TEST_UNSUPPORTED(".word 0xe089f0bb @ strh pc, [r9], r11") + TEST_UNSUPPORTED(".word 0xe089a0bf @ strh r10, [r9], pc") + + TEST_PR( "ldrh r0, [r",0, 48,", -r",2, 24,"]") + TEST_PR( "ldrcsh r14, [r",13,0, ", r",12, 48,"]") + TEST_PR( "ldrh r1, [r",2, 24,", r",3, 48,"]!") + TEST_PR( "ldrcch r12, [r",11,48,", -r",10,24,"]!") + TEST_PR( "ldrh r2, [r",3, 24,"], r",4, 48,"") + TEST_PR( "ldrh r10, [r",9, 48,"], -r",11,24,"") + TEST_UNSUPPORTED(".word 0xe1bfc0ba @ ldrh r12, [pc, r10]!") + TEST_UNSUPPORTED(".word 0xe099f0bb @ ldrh pc, [r9], r11") + TEST_UNSUPPORTED(".word 0xe099a0bf @ ldrh r10, [r9], pc") + + TEST_RP( "strh r",0, VAL1,", [r",1, 24,", #-2]") + TEST_RP( "strmih r",14,VAL2,", [r",13,0, ", #2]") + TEST_RP( "strh r",1, VAL1,", [r",2, 24,", #4]!") + TEST_RP( "strplh r",12,VAL2,", [r",11,24,", #-4]!") + TEST_RP( "strh r",2, VAL1,", [r",3, 24,"], #48") + TEST_RP( "strh r",10,VAL2,", [r",9, 64,"], #-48") + TEST_UNSUPPORTED(".word 0xe1efc3b0 @ strh r12, [pc, #48]!") + TEST_UNSUPPORTED(".word 0xe0c9f3b0 @ strh pc, [r9], #48") + + TEST_P( "ldrh r0, [r",0, 24,", #-2]") + TEST_P( "ldrvsh r14, [r",13,0, ", #2]") + TEST_P( "ldrh r1, [r",2, 24,", #4]!") + TEST_P( "ldrvch r12, [r",11,24,", #-4]!") + TEST_P( "ldrh r2, [r",3, 24,"], #48") + TEST_P( "ldrh r10, [r",9, 64,"], #-48") + TEST( "ldrh r0, [pc, #0]") + TEST_UNSUPPORTED(".word 0xe1ffc3b0 @ ldrh r12, [pc, #48]!") + TEST_UNSUPPORTED(".word 0xe0d9f3b0 @ ldrh pc, [r9], #48") + + TEST_PR( "ldrsb r0, [r",0, 48,", -r",2, 24,"]") + TEST_PR( "ldrhisb r14, [r",13,0,", r",12, 48,"]") + TEST_PR( "ldrsb r1, [r",2, 24,", r",3, 48,"]!") + TEST_PR( "ldrlssb r12, [r",11,48,", -r",10,24,"]!") + TEST_PR( "ldrsb r2, [r",3, 24,"], r",4, 48,"") + TEST_PR( "ldrsb r10, [r",9, 48,"], -r",11,24,"") + TEST_UNSUPPORTED(".word 0xe1bfc0da @ ldrsb r12, [pc, r10]!") + TEST_UNSUPPORTED(".word 0xe099f0db @ ldrsb pc, [r9], r11") + + TEST_P( "ldrsb r0, [r",0, 24,", #-1]") + TEST_P( "ldrgesb r14, [r",13,0, ", #1]") + TEST_P( "ldrsb r1, [r",2, 24,", #4]!") + TEST_P( "ldrltsb r12, [r",11,24,", #-4]!") + TEST_P( "ldrsb r2, [r",3, 24,"], #48") + TEST_P( "ldrsb r10, [r",9, 64,"], #-48") + TEST( "ldrsb r0, [pc, #0]") + TEST_UNSUPPORTED(".word 0xe1ffc3d0 @ ldrsb r12, [pc, #48]!") + TEST_UNSUPPORTED(".word 0xe0d9f3d0 @ ldrsb pc, [r9], #48") + + TEST_PR( "ldrsh r0, [r",0, 48,", -r",2, 24,"]") + TEST_PR( "ldrgtsh r14, [r",13,0, ", r",12, 48,"]") + TEST_PR( "ldrsh r1, [r",2, 24,", r",3, 48,"]!") + TEST_PR( "ldrlesh r12, [r",11,48,", -r",10,24,"]!") + TEST_PR( "ldrsh r2, [r",3, 24,"], r",4, 48,"") + TEST_PR( "ldrsh r10, [r",9, 48,"], -r",11,24,"") + TEST_UNSUPPORTED(".word 0xe1bfc0fa @ ldrsh r12, [pc, r10]!") + TEST_UNSUPPORTED(".word 0xe099f0fb @ ldrsh pc, [r9], r11") + + TEST_P( "ldrsh r0, [r",0, 24,", #-1]") + TEST_P( "ldreqsh r14, [r",13,0 ,", #1]") + TEST_P( "ldrsh r1, [r",2, 24,", #4]!") + TEST_P( "ldrnesh r12, [r",11,24,", #-4]!") + TEST_P( "ldrsh r2, [r",3, 24,"], #48") + TEST_P( "ldrsh r10, [r",9, 64,"], #-48") + TEST( "ldrsh r0, [pc, #0]") + TEST_UNSUPPORTED(".word 0xe1ffc3f0 @ ldrsh r12, [pc, #48]!") + TEST_UNSUPPORTED(".word 0xe0d9f3f0 @ ldrsh pc, [r9], #48") + +#if __LINUX_ARM_ARCH__ >= 7 + TEST_UNSUPPORTED("strht r1, [r2], r3") + TEST_UNSUPPORTED("ldrht r1, [r2], r3") + TEST_UNSUPPORTED("strht r1, [r2], #48") + TEST_UNSUPPORTED("ldrht r1, [r2], #48") + TEST_UNSUPPORTED("ldrsbt r1, [r2], r3") + TEST_UNSUPPORTED("ldrsbt r1, [r2], #48") + TEST_UNSUPPORTED("ldrsht r1, [r2], r3") + TEST_UNSUPPORTED("ldrsht r1, [r2], #48") +#endif + + TEST_RPR( "strd r",0, VAL1,", [r",1, 48,", -r",2,24,"]") + TEST_RPR( "strccd r",8, VAL2,", [r",13,0, ", r",12,48,"]") + TEST_RPR( "strd r",4, VAL1,", [r",2, 24,", r",3, 48,"]!") + TEST_RPR( "strcsd r",12,VAL2,", [r",11,48,", -r",10,24,"]!") + TEST_RPR( "strd r",2, VAL1,", [r",3, 24,"], r",4,48,"") + TEST_RPR( "strd r",10,VAL2,", [r",9, 48,"], -r",7,24,"") + TEST_UNSUPPORTED(".word 0xe1afc0fa @ strd r12, [pc, r10]!") + + TEST_PR( "ldrd r0, [r",0, 48,", -r",2,24,"]") + TEST_PR( "ldrmid r8, [r",13,0, ", r",12,48,"]") + TEST_PR( "ldrd r4, [r",2, 24,", r",3, 48,"]!") + TEST_PR( "ldrpld r6, [r",11,48,", -r",10,24,"]!") + TEST_PR( "ldrd r2, [r",5, 24,"], r",4,48,"") + TEST_PR( "ldrd r10, [r",9,48,"], -r",7,24,"") + TEST_UNSUPPORTED(".word 0xe1afc0da @ ldrd r12, [pc, r10]!") + TEST_UNSUPPORTED(".word 0xe089f0db @ ldrd pc, [r9], r11") + TEST_UNSUPPORTED(".word 0xe089e0db @ ldrd lr, [r9], r11") + TEST_UNSUPPORTED(".word 0xe089c0df @ ldrd r12, [r9], pc") + + TEST_RP( "strd r",0, VAL1,", [r",1, 24,", #-8]") + TEST_RP( "strvsd r",8, VAL2,", [r",13,0, ", #8]") + TEST_RP( "strd r",4, VAL1,", [r",2, 24,", #16]!") + TEST_RP( "strvcd r",12,VAL2,", [r",11,24,", #-16]!") + TEST_RP( "strd r",2, VAL1,", [r",4, 24,"], #48") + TEST_RP( "strd r",10,VAL2,", [r",9, 64,"], #-48") + TEST_UNSUPPORTED(".word 0xe1efc3f0 @ strd r12, [pc, #48]!") + + TEST_P( "ldrd r0, [r",0, 24,", #-8]") + TEST_P( "ldrhid r8, [r",13,0, ", #8]") + TEST_P( "ldrd r4, [r",2, 24,", #16]!") + TEST_P( "ldrlsd r6, [r",11,24,", #-16]!") + TEST_P( "ldrd r2, [r",5, 24,"], #48") + TEST_P( "ldrd r10, [r",9,6,"], #-48") + TEST_UNSUPPORTED(".word 0xe1efc3d0 @ ldrd r12, [pc, #48]!") + TEST_UNSUPPORTED(".word 0xe0c9f3d0 @ ldrd pc, [r9], #48") + TEST_UNSUPPORTED(".word 0xe0c9e3d0 @ ldrd lr, [r9], #48") + + TEST_GROUP("Miscellaneous") + +#if __LINUX_ARM_ARCH__ >= 7 + TEST("movw r0, #0") + TEST("movw r0, #0xffff") + TEST("movw lr, #0xffff") + TEST_UNSUPPORTED(".word 0xe300f000 @ movw pc, #0") + TEST_R("movt r",0, VAL1,", #0") + TEST_R("movt r",0, VAL2,", #0xffff") + TEST_R("movt r",14,VAL1,", #0xffff") + TEST_UNSUPPORTED(".word 0xe340f000 @ movt pc, #0") +#endif + + TEST_UNSUPPORTED("msr cpsr, 0x13") + TEST_UNSUPPORTED("msr cpsr_f, 0xf0000000") + TEST_UNSUPPORTED("msr spsr, 0x13") + +#if __LINUX_ARM_ARCH__ >= 7 + TEST_SUPPORTED("yield") + TEST("sev") + TEST("nop") + TEST("wfi") + TEST_SUPPORTED("wfe") + TEST_UNSUPPORTED("dbg #0") +#endif + + TEST_GROUP("Load/store word and unsigned byte") + +#define LOAD_STORE(byte) \ + TEST_RP( "str"byte" r",0, VAL1,", [r",1, 24,", #-2]") \ + TEST_RP( "str"byte" r",14,VAL2,", [r",13,0, ", #2]") \ + TEST_RP( "str"byte" r",1, VAL1,", [r",2, 24,", #4]!") \ + TEST_RP( "str"byte" r",12,VAL2,", [r",11,24,", #-4]!") \ + TEST_RP( "str"byte" r",2, VAL1,", [r",3, 24,"], #48") \ + TEST_RP( "str"byte" r",10,VAL2,", [r",9, 64,"], #-48") \ + TEST_RPR("str"byte" r",0, VAL1,", [r",1, 48,", -r",2, 24,"]") \ + TEST_RPR("str"byte" r",14,VAL2,", [r",13,0, ", r",12, 48,"]") \ + TEST_RPR("str"byte" r",1, VAL1,", [r",2, 24,", r",3, 48,"]!") \ + TEST_RPR("str"byte" r",12,VAL2,", [r",11,48,", -r",10,24,"]!") \ + TEST_RPR("str"byte" r",2, VAL1,", [r",3, 24,"], r",4, 48,"") \ + TEST_RPR("str"byte" r",10,VAL2,", [r",9, 48,"], -r",11,24,"") \ + TEST_RPR("str"byte" r",0, VAL1,", [r",1, 24,", r",2, 32,", asl #1]")\ + TEST_RPR("str"byte" r",14,VAL2,", [r",13,0, ", r",12, 32,", lsr #2]")\ + TEST_RPR("str"byte" r",1, VAL1,", [r",2, 24,", r",3, 32,", asr #3]!")\ + TEST_RPR("str"byte" r",12,VAL2,", [r",11,24,", r",10, 4,", ror #31]!")\ + TEST_P( "ldr"byte" r0, [r",0, 24,", #-2]") \ + TEST_P( "ldr"byte" r14, [r",13,0, ", #2]") \ + TEST_P( "ldr"byte" r1, [r",2, 24,", #4]!") \ + TEST_P( "ldr"byte" r12, [r",11,24,", #-4]!") \ + TEST_P( "ldr"byte" r2, [r",3, 24,"], #48") \ + TEST_P( "ldr"byte" r10, [r",9, 64,"], #-48") \ + TEST_PR( "ldr"byte" r0, [r",0, 48,", -r",2, 24,"]") \ + TEST_PR( "ldr"byte" r14, [r",13,0, ", r",12, 48,"]") \ + TEST_PR( "ldr"byte" r1, [r",2, 24,", r",3, 48,"]!") \ + TEST_PR( "ldr"byte" r12, [r",11,48,", -r",10,24,"]!") \ + TEST_PR( "ldr"byte" r2, [r",3, 24,"], r",4, 48,"") \ + TEST_PR( "ldr"byte" r10, [r",9, 48,"], -r",11,24,"") \ + TEST_PR( "ldr"byte" r0, [r",0, 24,", r",2, 32,", asl #1]") \ + TEST_PR( "ldr"byte" r14, [r",13,0, ", r",12, 32,", lsr #2]") \ + TEST_PR( "ldr"byte" r1, [r",2, 24,", r",3, 32,", asr #3]!") \ + TEST_PR( "ldr"byte" r12, [r",11,24,", r",10, 4,", ror #31]!") \ + TEST( "ldr"byte" r0, [pc, #0]") \ + TEST_R( "ldr"byte" r12, [pc, r",14,0,"]") + + LOAD_STORE("") + TEST_P( "str pc, [r",0,0,", #15*4]") + TEST_R( "str pc, [sp, r",2,15*4,"]") + TEST_BF( "ldr pc, [sp, #15*4]") + TEST_BF_R("ldr pc, [sp, r",2,15*4,"]") + + TEST_P( "str sp, [r",0,0,", #13*4]") + TEST_R( "str sp, [sp, r",2,13*4,"]") + TEST_BF( "ldr sp, [sp, #13*4]") + TEST_BF_R("ldr sp, [sp, r",2,13*4,"]") + +#ifdef CONFIG_THUMB2_KERNEL + TEST_ARM_TO_THUMB_INTERWORK_P("ldr pc, [r",0,0,", #15*4]") +#endif + TEST_UNSUPPORTED(".word 0xe5af6008 @ str r6, [pc, #8]!") + TEST_UNSUPPORTED(".word 0xe7af6008 @ str r6, [pc, r8]!") + TEST_UNSUPPORTED(".word 0xe5bf6008 @ ldr r6, [pc, #8]!") + TEST_UNSUPPORTED(".word 0xe7bf6008 @ ldr r6, [pc, r8]!") + TEST_UNSUPPORTED(".word 0xe788600f @ str r6, [r8, pc]") + TEST_UNSUPPORTED(".word 0xe798600f @ ldr r6, [r8, pc]") + + LOAD_STORE("b") + TEST_UNSUPPORTED(".word 0xe5f7f008 @ ldrb pc, [r7, #8]!") + TEST_UNSUPPORTED(".word 0xe7f7f008 @ ldrb pc, [r7, r8]!") + TEST_UNSUPPORTED(".word 0xe5ef6008 @ strb r6, [pc, #8]!") + TEST_UNSUPPORTED(".word 0xe7ef6008 @ strb r6, [pc, r3]!") + TEST_UNSUPPORTED(".word 0xe5ff6008 @ ldrb r6, [pc, #8]!") + TEST_UNSUPPORTED(".word 0xe7ff6008 @ ldrb r6, [pc, r3]!") + + TEST_UNSUPPORTED("ldrt r0, [r1], #4") + TEST_UNSUPPORTED("ldrt r1, [r2], r3") + TEST_UNSUPPORTED("strt r2, [r3], #4") + TEST_UNSUPPORTED("strt r3, [r4], r5") + TEST_UNSUPPORTED("ldrbt r4, [r5], #4") + TEST_UNSUPPORTED("ldrbt r5, [r6], r7") + TEST_UNSUPPORTED("strbt r6, [r7], #4") + TEST_UNSUPPORTED("strbt r7, [r8], r9") + +#if __LINUX_ARM_ARCH__ >= 7 + TEST_GROUP("Parallel addition and subtraction, signed") + + TEST_UNSUPPORTED(".word 0xe6000010") /* Unallocated space */ + TEST_UNSUPPORTED(".word 0xe60fffff") /* Unallocated space */ + + TEST_RR( "sadd16 r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "sadd16 r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe61cff1a @ sadd16 pc, r12, r10") + TEST_RR( "sasx r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "sasx r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe61cff3a @ sasx pc, r12, r10") + TEST_RR( "ssax r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "ssax r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe61cff5a @ ssax pc, r12, r10") + TEST_RR( "ssub16 r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "ssub16 r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe61cff7a @ ssub16 pc, r12, r10") + TEST_RR( "sadd8 r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "sadd8 r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe61cff9a @ sadd8 pc, r12, r10") + TEST_UNSUPPORTED(".word 0xe61000b0") /* Unallocated space */ + TEST_UNSUPPORTED(".word 0xe61fffbf") /* Unallocated space */ + TEST_UNSUPPORTED(".word 0xe61000d0") /* Unallocated space */ + TEST_UNSUPPORTED(".word 0xe61fffdf") /* Unallocated space */ + TEST_RR( "ssub8 r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "ssub8 r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe61cfffa @ ssub8 pc, r12, r10") + + TEST_RR( "qadd16 r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "qadd16 r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe62cff1a @ qadd16 pc, r12, r10") + TEST_RR( "qasx r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "qasx r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe62cff3a @ qasx pc, r12, r10") + TEST_RR( "qsax r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "qsax r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe62cff5a @ qsax pc, r12, r10") + TEST_RR( "qsub16 r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "qsub16 r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe62cff7a @ qsub16 pc, r12, r10") + TEST_RR( "qadd8 r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "qadd8 r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe62cff9a @ qadd8 pc, r12, r10") + TEST_UNSUPPORTED(".word 0xe62000b0") /* Unallocated space */ + TEST_UNSUPPORTED(".word 0xe62fffbf") /* Unallocated space */ + TEST_UNSUPPORTED(".word 0xe62000d0") /* Unallocated space */ + TEST_UNSUPPORTED(".word 0xe62fffdf") /* Unallocated space */ + TEST_RR( "qsub8 r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "qsub8 r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe62cfffa @ qsub8 pc, r12, r10") + + TEST_RR( "shadd16 r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "shadd16 r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe63cff1a @ shadd16 pc, r12, r10") + TEST_RR( "shasx r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "shasx r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe63cff3a @ shasx pc, r12, r10") + TEST_RR( "shsax r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "shsax r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe63cff5a @ shsax pc, r12, r10") + TEST_RR( "shsub16 r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "shsub16 r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe63cff7a @ shsub16 pc, r12, r10") + TEST_RR( "shadd8 r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "shadd8 r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe63cff9a @ shadd8 pc, r12, r10") + TEST_UNSUPPORTED(".word 0xe63000b0") /* Unallocated space */ + TEST_UNSUPPORTED(".word 0xe63fffbf") /* Unallocated space */ + TEST_UNSUPPORTED(".word 0xe63000d0") /* Unallocated space */ + TEST_UNSUPPORTED(".word 0xe63fffdf") /* Unallocated space */ + TEST_RR( "shsub8 r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "shsub8 r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe63cfffa @ shsub8 pc, r12, r10") + + TEST_GROUP("Parallel addition and subtraction, unsigned") + + TEST_UNSUPPORTED(".word 0xe6400010") /* Unallocated space */ + TEST_UNSUPPORTED(".word 0xe64fffff") /* Unallocated space */ + + TEST_RR( "uadd16 r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "uadd16 r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe65cff1a @ uadd16 pc, r12, r10") + TEST_RR( "uasx r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "uasx r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe65cff3a @ uasx pc, r12, r10") + TEST_RR( "usax r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "usax r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe65cff5a @ usax pc, r12, r10") + TEST_RR( "usub16 r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "usub16 r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe65cff7a @ usub16 pc, r12, r10") + TEST_RR( "uadd8 r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "uadd8 r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe65cff9a @ uadd8 pc, r12, r10") + TEST_UNSUPPORTED(".word 0xe65000b0") /* Unallocated space */ + TEST_UNSUPPORTED(".word 0xe65fffbf") /* Unallocated space */ + TEST_UNSUPPORTED(".word 0xe65000d0") /* Unallocated space */ + TEST_UNSUPPORTED(".word 0xe65fffdf") /* Unallocated space */ + TEST_RR( "usub8 r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "usub8 r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe65cfffa @ usub8 pc, r12, r10") + + TEST_RR( "uqadd16 r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "uqadd16 r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe66cff1a @ uqadd16 pc, r12, r10") + TEST_RR( "uqasx r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "uqasx r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe66cff3a @ uqasx pc, r12, r10") + TEST_RR( "uqsax r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "uqsax r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe66cff5a @ uqsax pc, r12, r10") + TEST_RR( "uqsub16 r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "uqsub16 r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe66cff7a @ uqsub16 pc, r12, r10") + TEST_RR( "uqadd8 r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "uqadd8 r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe66cff9a @ uqadd8 pc, r12, r10") + TEST_UNSUPPORTED(".word 0xe66000b0") /* Unallocated space */ + TEST_UNSUPPORTED(".word 0xe66fffbf") /* Unallocated space */ + TEST_UNSUPPORTED(".word 0xe66000d0") /* Unallocated space */ + TEST_UNSUPPORTED(".word 0xe66fffdf") /* Unallocated space */ + TEST_RR( "uqsub8 r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "uqsub8 r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe66cfffa @ uqsub8 pc, r12, r10") + + TEST_RR( "uhadd16 r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "uhadd16 r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe67cff1a @ uhadd16 pc, r12, r10") + TEST_RR( "uhasx r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "uhasx r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe67cff3a @ uhasx pc, r12, r10") + TEST_RR( "uhsax r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "uhsax r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe67cff5a @ uhsax pc, r12, r10") + TEST_RR( "uhsub16 r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "uhsub16 r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe67cff7a @ uhsub16 pc, r12, r10") + TEST_RR( "uhadd8 r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "uhadd8 r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe67cff9a @ uhadd8 pc, r12, r10") + TEST_UNSUPPORTED(".word 0xe67000b0") /* Unallocated space */ + TEST_UNSUPPORTED(".word 0xe67fffbf") /* Unallocated space */ + TEST_UNSUPPORTED(".word 0xe67000d0") /* Unallocated space */ + TEST_UNSUPPORTED(".word 0xe67fffdf") /* Unallocated space */ + TEST_RR( "uhsub8 r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "uhsub8 r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe67cfffa @ uhsub8 pc, r12, r10") + TEST_UNSUPPORTED(".word 0xe67feffa @ uhsub8 r14, pc, r10") + TEST_UNSUPPORTED(".word 0xe67cefff @ uhsub8 r14, r12, pc") +#endif /* __LINUX_ARM_ARCH__ >= 7 */ + +#if __LINUX_ARM_ARCH__ >= 6 + TEST_GROUP("Packing, unpacking, saturation, and reversal") + + TEST_RR( "pkhbt r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "pkhbt r14,r",12, HH1,", r",10,HH2,", lsl #2") + TEST_UNSUPPORTED(".word 0xe68cf11a @ pkhbt pc, r12, r10, lsl #2") + TEST_RR( "pkhtb r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "pkhtb r14,r",12, HH1,", r",10,HH2,", asr #2") + TEST_UNSUPPORTED(".word 0xe68cf15a @ pkhtb pc, r12, r10, asr #2") + TEST_UNSUPPORTED(".word 0xe68fe15a @ pkhtb r14, pc, r10, asr #2") + TEST_UNSUPPORTED(".word 0xe68ce15f @ pkhtb r14, r12, pc, asr #2") + TEST_UNSUPPORTED(".word 0xe6900010") /* Unallocated space */ + TEST_UNSUPPORTED(".word 0xe69fffdf") /* Unallocated space */ + + TEST_R( "ssat r0, #24, r",0, VAL1,"") + TEST_R( "ssat r14, #24, r",12, VAL2,"") + TEST_R( "ssat r0, #24, r",0, VAL1,", lsl #8") + TEST_R( "ssat r14, #24, r",12, VAL2,", asr #8") + TEST_UNSUPPORTED(".word 0xe6b7f01c @ ssat pc, #24, r12") + + TEST_R( "usat r0, #24, r",0, VAL1,"") + TEST_R( "usat r14, #24, r",12, VAL2,"") + TEST_R( "usat r0, #24, r",0, VAL1,", lsl #8") + TEST_R( "usat r14, #24, r",12, VAL2,", asr #8") + TEST_UNSUPPORTED(".word 0xe6f7f01c @ usat pc, #24, r12") + + TEST_RR( "sxtab16 r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "sxtab16 r14,r",12, HH2,", r",10,HH1,", ror #8") + TEST_R( "sxtb16 r8, r",7, HH1,"") + TEST_UNSUPPORTED(".word 0xe68cf47a @ sxtab16 pc,r12, r10, ror #8") + + TEST_RR( "sel r0, r",0, VAL1,", r",1, VAL2,"") + TEST_RR( "sel r14, r",12,VAL1,", r",10, VAL2,"") + TEST_UNSUPPORTED(".word 0xe68cffba @ sel pc, r12, r10") + TEST_UNSUPPORTED(".word 0xe68fefba @ sel r14, pc, r10") + TEST_UNSUPPORTED(".word 0xe68cefbf @ sel r14, r12, pc") + + TEST_R( "ssat16 r0, #12, r",0, HH1,"") + TEST_R( "ssat16 r14, #12, r",12, HH2,"") + TEST_UNSUPPORTED(".word 0xe6abff3c @ ssat16 pc, #12, r12") + + TEST_RR( "sxtab r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "sxtab r14,r",12, HH2,", r",10,HH1,", ror #8") + TEST_R( "sxtb r8, r",7, HH1,"") + TEST_UNSUPPORTED(".word 0xe6acf47a @ sxtab pc,r12, r10, ror #8") + + TEST_R( "rev r0, r",0, VAL1,"") + TEST_R( "rev r14, r",12, VAL2,"") + TEST_UNSUPPORTED(".word 0xe6bfff3c @ rev pc, r12") + + TEST_RR( "sxtah r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "sxtah r14,r",12, HH2,", r",10,HH1,", ror #8") + TEST_R( "sxth r8, r",7, HH1,"") + TEST_UNSUPPORTED(".word 0xe6bcf47a @ sxtah pc,r12, r10, ror #8") + + TEST_R( "rev16 r0, r",0, VAL1,"") + TEST_R( "rev16 r14, r",12, VAL2,"") + TEST_UNSUPPORTED(".word 0xe6bfffbc @ rev16 pc, r12") + + TEST_RR( "uxtab16 r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "uxtab16 r14,r",12, HH2,", r",10,HH1,", ror #8") + TEST_R( "uxtb16 r8, r",7, HH1,"") + TEST_UNSUPPORTED(".word 0xe6ccf47a @ uxtab16 pc,r12, r10, ror #8") + + TEST_R( "usat16 r0, #12, r",0, HH1,"") + TEST_R( "usat16 r14, #12, r",12, HH2,"") + TEST_UNSUPPORTED(".word 0xe6ecff3c @ usat16 pc, #12, r12") + TEST_UNSUPPORTED(".word 0xe6ecef3f @ usat16 r14, #12, pc") + + TEST_RR( "uxtab r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "uxtab r14,r",12, HH2,", r",10,HH1,", ror #8") + TEST_R( "uxtb r8, r",7, HH1,"") + TEST_UNSUPPORTED(".word 0xe6ecf47a @ uxtab pc,r12, r10, ror #8") + +#if __LINUX_ARM_ARCH__ >= 7 + TEST_R( "rbit r0, r",0, VAL1,"") + TEST_R( "rbit r14, r",12, VAL2,"") + TEST_UNSUPPORTED(".word 0xe6ffff3c @ rbit pc, r12") +#endif + + TEST_RR( "uxtah r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "uxtah r14,r",12, HH2,", r",10,HH1,", ror #8") + TEST_R( "uxth r8, r",7, HH1,"") + TEST_UNSUPPORTED(".word 0xe6fff077 @ uxth pc, r7") + TEST_UNSUPPORTED(".word 0xe6ff807f @ uxth r8, pc") + TEST_UNSUPPORTED(".word 0xe6fcf47a @ uxtah pc, r12, r10, ror #8") + TEST_UNSUPPORTED(".word 0xe6fce47f @ uxtah r14, r12, pc, ror #8") + + TEST_R( "revsh r0, r",0, VAL1,"") + TEST_R( "revsh r14, r",12, VAL2,"") + TEST_UNSUPPORTED(".word 0xe6ffff3c @ revsh pc, r12") + TEST_UNSUPPORTED(".word 0xe6ffef3f @ revsh r14, pc") + + TEST_UNSUPPORTED(".word 0xe6900070") /* Unallocated space */ + TEST_UNSUPPORTED(".word 0xe69fff7f") /* Unallocated space */ + + TEST_UNSUPPORTED(".word 0xe6d00070") /* Unallocated space */ + TEST_UNSUPPORTED(".word 0xe6dfff7f") /* Unallocated space */ +#endif /* __LINUX_ARM_ARCH__ >= 6 */ + +#if __LINUX_ARM_ARCH__ >= 6 + TEST_GROUP("Signed multiplies") + + TEST_RRR( "smlad r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"") + TEST_RRR( "smlad r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"") + TEST_UNSUPPORTED(".word 0xe70f8a1c @ smlad pc, r12, r10, r8") + TEST_RRR( "smladx r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"") + TEST_RRR( "smladx r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"") + TEST_UNSUPPORTED(".word 0xe70f8a3c @ smladx pc, r12, r10, r8") + + TEST_RR( "smuad r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "smuad r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe70ffa1c @ smuad pc, r12, r10") + TEST_RR( "smuadx r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "smuadx r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe70ffa3c @ smuadx pc, r12, r10") + + TEST_RRR( "smlsd r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"") + TEST_RRR( "smlsd r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"") + TEST_UNSUPPORTED(".word 0xe70f8a5c @ smlsd pc, r12, r10, r8") + TEST_RRR( "smlsdx r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"") + TEST_RRR( "smlsdx r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"") + TEST_UNSUPPORTED(".word 0xe70f8a7c @ smlsdx pc, r12, r10, r8") + + TEST_RR( "smusd r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "smusd r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe70ffa5c @ smusd pc, r12, r10") + TEST_RR( "smusdx r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "smusdx r14, r",12,HH2,", r",10,HH1,"") + TEST_UNSUPPORTED(".word 0xe70ffa7c @ smusdx pc, r12, r10") + + TEST_RRRR( "smlald r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2) + TEST_RRRR( "smlald r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1) + TEST_UNSUPPORTED(".word 0xe74af819 @ smlald pc, r10, r9, r8") + TEST_UNSUPPORTED(".word 0xe74fb819 @ smlald r11, pc, r9, r8") + TEST_UNSUPPORTED(".word 0xe74ab81f @ smlald r11, r10, pc, r8") + TEST_UNSUPPORTED(".word 0xe74abf19 @ smlald r11, r10, r9, pc") + + TEST_RRRR( "smlaldx r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2) + TEST_RRRR( "smlaldx r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1) + TEST_UNSUPPORTED(".word 0xe74af839 @ smlaldx pc, r10, r9, r8") + TEST_UNSUPPORTED(".word 0xe74fb839 @ smlaldx r11, pc, r9, r8") + + TEST_RRR( "smmla r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"") + TEST_RRR( "smmla r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"") + TEST_UNSUPPORTED(".word 0xe75f8a1c @ smmla pc, r12, r10, r8") + TEST_RRR( "smmlar r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"") + TEST_RRR( "smmlar r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"") + TEST_UNSUPPORTED(".word 0xe75f8a3c @ smmlar pc, r12, r10, r8") + + TEST_RR( "smmul r0, r",0, VAL1,", r",1, VAL2,"") + TEST_RR( "smmul r14, r",12,VAL2,", r",10,VAL1,"") + TEST_UNSUPPORTED(".word 0xe75ffa1c @ smmul pc, r12, r10") + TEST_RR( "smmulr r0, r",0, VAL1,", r",1, VAL2,"") + TEST_RR( "smmulr r14, r",12,VAL2,", r",10,VAL1,"") + TEST_UNSUPPORTED(".word 0xe75ffa3c @ smmulr pc, r12, r10") + + TEST_RRR( "smmls r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"") + TEST_RRR( "smmls r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"") + TEST_UNSUPPORTED(".word 0xe75f8adc @ smmls pc, r12, r10, r8") + TEST_RRR( "smmlsr r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"") + TEST_RRR( "smmlsr r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"") + TEST_UNSUPPORTED(".word 0xe75f8afc @ smmlsr pc, r12, r10, r8") + TEST_UNSUPPORTED(".word 0xe75e8aff @ smmlsr r14, pc, r10, r8") + TEST_UNSUPPORTED(".word 0xe75e8ffc @ smmlsr r14, r12, pc, r8") + TEST_UNSUPPORTED(".word 0xe75efafc @ smmlsr r14, r12, r10, pc") + + TEST_RR( "usad8 r0, r",0, VAL1,", r",1, VAL2,"") + TEST_RR( "usad8 r14, r",12,VAL2,", r",10,VAL1,"") + TEST_UNSUPPORTED(".word 0xe75ffa1c @ usad8 pc, r12, r10") + TEST_UNSUPPORTED(".word 0xe75efa1f @ usad8 r14, pc, r10") + TEST_UNSUPPORTED(".word 0xe75eff1c @ usad8 r14, r12, pc") + + TEST_RRR( "usada8 r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL3,"") + TEST_RRR( "usada8 r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL3,"") + TEST_UNSUPPORTED(".word 0xe78f8a1c @ usada8 pc, r12, r10, r8") + TEST_UNSUPPORTED(".word 0xe78e8a1f @ usada8 r14, pc, r10, r8") + TEST_UNSUPPORTED(".word 0xe78e8f1c @ usada8 r14, r12, pc, r8") +#endif /* __LINUX_ARM_ARCH__ >= 6 */ + +#if __LINUX_ARM_ARCH__ >= 7 + TEST_GROUP("Bit Field") + + TEST_R( "sbfx r0, r",0 , VAL1,", #0, #31") + TEST_R( "sbfxeq r14, r",12, VAL2,", #8, #16") + TEST_R( "sbfx r4, r",10, VAL1,", #16, #15") + TEST_UNSUPPORTED(".word 0xe7aff45c @ sbfx pc, r12, #8, #16") + + TEST_R( "ubfx r0, r",0 , VAL1,", #0, #31") + TEST_R( "ubfxcs r14, r",12, VAL2,", #8, #16") + TEST_R( "ubfx r4, r",10, VAL1,", #16, #15") + TEST_UNSUPPORTED(".word 0xe7eff45c @ ubfx pc, r12, #8, #16") + TEST_UNSUPPORTED(".word 0xe7efc45f @ ubfx r12, pc, #8, #16") + + TEST_R( "bfc r",0, VAL1,", #4, #20") + TEST_R( "bfcvs r",14,VAL2,", #4, #20") + TEST_R( "bfc r",7, VAL1,", #0, #31") + TEST_R( "bfc r",8, VAL2,", #0, #31") + TEST_UNSUPPORTED(".word 0xe7def01f @ bfc pc, #0, #31"); + + TEST_RR( "bfi r",0, VAL1,", r",0 , VAL2,", #0, #31") + TEST_RR( "bfipl r",12,VAL1,", r",14 , VAL2,", #4, #20") + TEST_UNSUPPORTED(".word 0xe7d7f21e @ bfi pc, r14, #4, #20") + + TEST_UNSUPPORTED(".word 0x07f000f0") /* Permanently UNDEFINED */ + TEST_UNSUPPORTED(".word 0x07ffffff") /* Permanently UNDEFINED */ +#endif /* __LINUX_ARM_ARCH__ >= 6 */ + + TEST_GROUP("Branch, branch with link, and block data transfer") + + TEST_P( "stmda r",0, 16*4,", {r0}") + TEST_P( "stmeqda r",4, 16*4,", {r0-r15}") + TEST_P( "stmneda r",8, 16*4,"!, {r8-r15}") + TEST_P( "stmda r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}") + TEST_P( "stmda r",13,0, "!, {pc}") + + TEST_P( "ldmda r",0, 16*4,", {r0}") + TEST_BF_P("ldmcsda r",4, 15*4,", {r0-r15}") + TEST_BF_P("ldmccda r",7, 15*4,"!, {r8-r15}") + TEST_P( "ldmda r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}") + TEST_BF_P("ldmda r",14,15*4,"!, {pc}") + + TEST_P( "stmia r",0, 16*4,", {r0}") + TEST_P( "stmmiia r",4, 16*4,", {r0-r15}") + TEST_P( "stmplia r",8, 16*4,"!, {r8-r15}") + TEST_P( "stmia r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}") + TEST_P( "stmia r",14,0, "!, {pc}") + + TEST_P( "ldmia r",0, 16*4,", {r0}") + TEST_BF_P("ldmvsia r",4, 0, ", {r0-r15}") + TEST_BF_P("ldmvcia r",7, 8*4, "!, {r8-r15}") + TEST_P( "ldmia r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}") + TEST_BF_P("ldmia r",14,15*4,"!, {pc}") + + TEST_P( "stmdb r",0, 16*4,", {r0}") + TEST_P( "stmhidb r",4, 16*4,", {r0-r15}") + TEST_P( "stmlsdb r",8, 16*4,"!, {r8-r15}") + TEST_P( "stmdb r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}") + TEST_P( "stmdb r",13,4, "!, {pc}") + + TEST_P( "ldmdb r",0, 16*4,", {r0}") + TEST_BF_P("ldmgedb r",4, 16*4,", {r0-r15}") + TEST_BF_P("ldmltdb r",7, 16*4,"!, {r8-r15}") + TEST_P( "ldmdb r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}") + TEST_BF_P("ldmdb r",14,16*4,"!, {pc}") + + TEST_P( "stmib r",0, 16*4,", {r0}") + TEST_P( "stmgtib r",4, 16*4,", {r0-r15}") + TEST_P( "stmleib r",8, 16*4,"!, {r8-r15}") + TEST_P( "stmib r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}") + TEST_P( "stmib r",13,-4, "!, {pc}") + + TEST_P( "ldmib r",0, 16*4,", {r0}") + TEST_BF_P("ldmeqib r",4, -4,", {r0-r15}") + TEST_BF_P("ldmneib r",7, 7*4,"!, {r8-r15}") + TEST_P( "ldmib r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}") + TEST_BF_P("ldmib r",14,14*4,"!, {pc}") + + TEST_P( "stmdb r",13,16*4,"!, {r3-r12,lr}") + TEST_P( "stmeqdb r",13,16*4,"!, {r3-r12}") + TEST_P( "stmnedb r",2, 16*4,", {r3-r12,lr}") + TEST_P( "stmdb r",13,16*4,"!, {r2-r12,lr}") + TEST_P( "stmdb r",0, 16*4,", {r0-r12}") + TEST_P( "stmdb r",0, 16*4,", {r0-r12,lr}") + + TEST_BF_P("ldmia r",13,5*4, "!, {r3-r12,pc}") + TEST_P( "ldmccia r",13,5*4, "!, {r3-r12}") + TEST_BF_P("ldmcsia r",2, 5*4, "!, {r3-r12,pc}") + TEST_BF_P("ldmia r",13,4*4, "!, {r2-r12,pc}") + TEST_P( "ldmia r",0, 16*4,", {r0-r12}") + TEST_P( "ldmia r",0, 16*4,", {r0-r12,lr}") + +#ifdef CONFIG_THUMB2_KERNEL + TEST_ARM_TO_THUMB_INTERWORK_P("ldmplia r",0,15*4,", {pc}") + TEST_ARM_TO_THUMB_INTERWORK_P("ldmmiia r",13,0,", {r0-r15}") +#endif + TEST_BF("b 2f") + TEST_BF("bl 2f") + TEST_BB("b 2b") + TEST_BB("bl 2b") + + TEST_BF("beq 2f") + TEST_BF("bleq 2f") + TEST_BB("bne 2b") + TEST_BB("blne 2b") + + TEST_BF("bgt 2f") + TEST_BF("blgt 2f") + TEST_BB("blt 2b") + TEST_BB("bllt 2b") + + TEST_GROUP("Supervisor Call, and coprocessor instructions") + + /* + * We can't really test these by executing them, so all + * we can do is check that probes are, or are not allowed. + * At the moment none are allowed... + */ +#define TEST_COPROCESSOR(code) TEST_UNSUPPORTED(code) + +#define COPROCESSOR_INSTRUCTIONS_ST_LD(two,cc) \ + TEST_COPROCESSOR("stc"two" 0, cr0, [r13, #4]") \ + TEST_COPROCESSOR("stc"two" 0, cr0, [r13, #-4]") \ + TEST_COPROCESSOR("stc"two" 0, cr0, [r13, #4]!") \ + TEST_COPROCESSOR("stc"two" 0, cr0, [r13, #-4]!") \ + TEST_COPROCESSOR("stc"two" 0, cr0, [r13], #4") \ + TEST_COPROCESSOR("stc"two" 0, cr0, [r13], #-4") \ + TEST_COPROCESSOR("stc"two" 0, cr0, [r13], {1}") \ + TEST_COPROCESSOR("stc"two"l 0, cr0, [r13, #4]") \ + TEST_COPROCESSOR("stc"two"l 0, cr0, [r13, #-4]") \ + TEST_COPROCESSOR("stc"two"l 0, cr0, [r13, #4]!") \ + TEST_COPROCESSOR("stc"two"l 0, cr0, [r13, #-4]!") \ + TEST_COPROCESSOR("stc"two"l 0, cr0, [r13], #4") \ + TEST_COPROCESSOR("stc"two"l 0, cr0, [r13], #-4") \ + TEST_COPROCESSOR("stc"two"l 0, cr0, [r13], {1}") \ + TEST_COPROCESSOR("ldc"two" 0, cr0, [r13, #4]") \ + TEST_COPROCESSOR("ldc"two" 0, cr0, [r13, #-4]") \ + TEST_COPROCESSOR("ldc"two" 0, cr0, [r13, #4]!") \ + TEST_COPROCESSOR("ldc"two" 0, cr0, [r13, #-4]!") \ + TEST_COPROCESSOR("ldc"two" 0, cr0, [r13], #4") \ + TEST_COPROCESSOR("ldc"two" 0, cr0, [r13], #-4") \ + TEST_COPROCESSOR("ldc"two" 0, cr0, [r13], {1}") \ + TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13, #4]") \ + TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13, #-4]") \ + TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13, #4]!") \ + TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13, #-4]!") \ + TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13], #4") \ + TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13], #-4") \ + TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13], {1}") \ + \ + TEST_COPROCESSOR( "stc"two" 0, cr0, [r15, #4]") \ + TEST_COPROCESSOR( "stc"two" 0, cr0, [r15, #-4]") \ + TEST_UNSUPPORTED(".word 0x"cc"daf0001 @ stc"two" 0, cr0, [r15, #4]!") \ + TEST_UNSUPPORTED(".word 0x"cc"d2f0001 @ stc"two" 0, cr0, [r15, #-4]!") \ + TEST_UNSUPPORTED(".word 0x"cc"caf0001 @ stc"two" 0, cr0, [r15], #4") \ + TEST_UNSUPPORTED(".word 0x"cc"c2f0001 @ stc"two" 0, cr0, [r15], #-4") \ + TEST_COPROCESSOR( "stc"two" 0, cr0, [r15], {1}") \ + TEST_COPROCESSOR( "stc"two"l 0, cr0, [r15, #4]") \ + TEST_COPROCESSOR( "stc"two"l 0, cr0, [r15, #-4]") \ + TEST_UNSUPPORTED(".word 0x"cc"def0001 @ stc"two"l 0, cr0, [r15, #4]!") \ + TEST_UNSUPPORTED(".word 0x"cc"d6f0001 @ stc"two"l 0, cr0, [r15, #-4]!") \ + TEST_UNSUPPORTED(".word 0x"cc"cef0001 @ stc"two"l 0, cr0, [r15], #4") \ + TEST_UNSUPPORTED(".word 0x"cc"c6f0001 @ stc"two"l 0, cr0, [r15], #-4") \ + TEST_COPROCESSOR( "stc"two"l 0, cr0, [r15], {1}") \ + TEST_COPROCESSOR( "ldc"two" 0, cr0, [r15, #4]") \ + TEST_COPROCESSOR( "ldc"two" 0, cr0, [r15, #-4]") \ + TEST_UNSUPPORTED(".word 0x"cc"dbf0001 @ ldc"two" 0, cr0, [r15, #4]!") \ + TEST_UNSUPPORTED(".word 0x"cc"d3f0001 @ ldc"two" 0, cr0, [r15, #-4]!") \ + TEST_UNSUPPORTED(".word 0x"cc"cbf0001 @ ldc"two" 0, cr0, [r15], #4") \ + TEST_UNSUPPORTED(".word 0x"cc"c3f0001 @ ldc"two" 0, cr0, [r15], #-4") \ + TEST_COPROCESSOR( "ldc"two" 0, cr0, [r15], {1}") \ + TEST_COPROCESSOR( "ldc"two"l 0, cr0, [r15, #4]") \ + TEST_COPROCESSOR( "ldc"two"l 0, cr0, [r15, #-4]") \ + TEST_UNSUPPORTED(".word 0x"cc"dff0001 @ ldc"two"l 0, cr0, [r15, #4]!") \ + TEST_UNSUPPORTED(".word 0x"cc"d7f0001 @ ldc"two"l 0, cr0, [r15, #-4]!") \ + TEST_UNSUPPORTED(".word 0x"cc"cff0001 @ ldc"two"l 0, cr0, [r15], #4") \ + TEST_UNSUPPORTED(".word 0x"cc"c7f0001 @ ldc"two"l 0, cr0, [r15], #-4") \ + TEST_COPROCESSOR( "ldc"two"l 0, cr0, [r15], {1}") + +#define COPROCESSOR_INSTRUCTIONS_MC_MR(two,cc) \ + \ + TEST_COPROCESSOR( "mcrr"two" 0, 15, r0, r14, cr0") \ + TEST_COPROCESSOR( "mcrr"two" 15, 0, r14, r0, cr15") \ + TEST_UNSUPPORTED(".word 0x"cc"c4f00f0 @ mcrr"two" 0, 15, r0, r15, cr0") \ + TEST_UNSUPPORTED(".word 0x"cc"c40ff0f @ mcrr"two" 15, 0, r15, r0, cr15") \ + TEST_COPROCESSOR( "mrrc"two" 0, 15, r0, r14, cr0") \ + TEST_COPROCESSOR( "mrrc"two" 15, 0, r14, r0, cr15") \ + TEST_UNSUPPORTED(".word 0x"cc"c5f00f0 @ mrrc"two" 0, 15, r0, r15, cr0") \ + TEST_UNSUPPORTED(".word 0x"cc"c50ff0f @ mrrc"two" 15, 0, r15, r0, cr15") \ + TEST_COPROCESSOR( "cdp"two" 15, 15, cr15, cr15, cr15, 7") \ + TEST_COPROCESSOR( "cdp"two" 0, 0, cr0, cr0, cr0, 0") \ + TEST_COPROCESSOR( "mcr"two" 15, 7, r15, cr15, cr15, 7") \ + TEST_COPROCESSOR( "mcr"two" 0, 0, r0, cr0, cr0, 0") \ + TEST_COPROCESSOR( "mrc"two" 15, 7, r15, cr15, cr15, 7") \ + TEST_COPROCESSOR( "mrc"two" 0, 0, r0, cr0, cr0, 0") + + COPROCESSOR_INSTRUCTIONS_ST_LD("","e") + COPROCESSOR_INSTRUCTIONS_MC_MR("","e") + TEST_UNSUPPORTED("svc 0") + TEST_UNSUPPORTED("svc 0xffffff") + + TEST_UNSUPPORTED("svc 0") + + TEST_GROUP("Unconditional instruction") + +#if __LINUX_ARM_ARCH__ >= 6 + TEST_UNSUPPORTED("srsda sp, 0x13") + TEST_UNSUPPORTED("srsdb sp, 0x13") + TEST_UNSUPPORTED("srsia sp, 0x13") + TEST_UNSUPPORTED("srsib sp, 0x13") + TEST_UNSUPPORTED("srsda sp!, 0x13") + TEST_UNSUPPORTED("srsdb sp!, 0x13") + TEST_UNSUPPORTED("srsia sp!, 0x13") + TEST_UNSUPPORTED("srsib sp!, 0x13") + + TEST_UNSUPPORTED("rfeda sp") + TEST_UNSUPPORTED("rfedb sp") + TEST_UNSUPPORTED("rfeia sp") + TEST_UNSUPPORTED("rfeib sp") + TEST_UNSUPPORTED("rfeda sp!") + TEST_UNSUPPORTED("rfedb sp!") + TEST_UNSUPPORTED("rfeia sp!") + TEST_UNSUPPORTED("rfeib sp!") + TEST_UNSUPPORTED(".word 0xf81d0a00 @ rfeda pc") + TEST_UNSUPPORTED(".word 0xf91d0a00 @ rfedb pc") + TEST_UNSUPPORTED(".word 0xf89d0a00 @ rfeia pc") + TEST_UNSUPPORTED(".word 0xf99d0a00 @ rfeib pc") + TEST_UNSUPPORTED(".word 0xf83d0a00 @ rfeda pc!") + TEST_UNSUPPORTED(".word 0xf93d0a00 @ rfedb pc!") + TEST_UNSUPPORTED(".word 0xf8bd0a00 @ rfeia pc!") + TEST_UNSUPPORTED(".word 0xf9bd0a00 @ rfeib pc!") +#endif /* __LINUX_ARM_ARCH__ >= 6 */ + +#if __LINUX_ARM_ARCH__ >= 6 + TEST_X( "blx __dummy_thumb_subroutine_even", + ".thumb \n\t" + ".space 4 \n\t" + ".type __dummy_thumb_subroutine_even, %%function \n\t" + "__dummy_thumb_subroutine_even: \n\t" + "mov r0, pc \n\t" + "bx lr \n\t" + ".arm \n\t" + ) + TEST( "blx __dummy_thumb_subroutine_even") + + TEST_X( "blx __dummy_thumb_subroutine_odd", + ".thumb \n\t" + ".space 2 \n\t" + ".type __dummy_thumb_subroutine_odd, %%function \n\t" + "__dummy_thumb_subroutine_odd: \n\t" + "mov r0, pc \n\t" + "bx lr \n\t" + ".arm \n\t" + ) + TEST( "blx __dummy_thumb_subroutine_odd") +#endif /* __LINUX_ARM_ARCH__ >= 6 */ + + COPROCESSOR_INSTRUCTIONS_ST_LD("2","f") +#if __LINUX_ARM_ARCH__ >= 6 + COPROCESSOR_INSTRUCTIONS_MC_MR("2","f") +#endif + + TEST_GROUP("Miscellaneous instructions, memory hints, and Advanced SIMD instructions") + +#if __LINUX_ARM_ARCH__ >= 6 + TEST_UNSUPPORTED("cps 0x13") + TEST_UNSUPPORTED("cpsie i") + TEST_UNSUPPORTED("cpsid i") + TEST_UNSUPPORTED("cpsie i,0x13") + TEST_UNSUPPORTED("cpsid i,0x13") + TEST_UNSUPPORTED("setend le") + TEST_UNSUPPORTED("setend be") +#endif + +#if __LINUX_ARM_ARCH__ >= 7 + TEST_P("pli [r",0,0b,", #16]") + TEST( "pli [pc, #0]") + TEST_RR("pli [r",12,0b,", r",0, 16,"]") + TEST_RR("pli [r",0, 0b,", -r",12,16,", lsl #4]") +#endif + +#if __LINUX_ARM_ARCH__ >= 5 + TEST_P("pld [r",0,32,", #-16]") + TEST( "pld [pc, #0]") + TEST_PR("pld [r",7, 24, ", r",0, 16,"]") + TEST_PR("pld [r",8, 24, ", -r",12,16,", lsl #4]") +#endif + +#if __LINUX_ARM_ARCH__ >= 7 + TEST_SUPPORTED( ".word 0xf590f000 @ pldw [r0, #0]") + TEST_SUPPORTED( ".word 0xf797f000 @ pldw [r7, r0]") + TEST_SUPPORTED( ".word 0xf798f18c @ pldw [r8, r12, lsl #3]"); +#endif + +#if __LINUX_ARM_ARCH__ >= 7 + TEST_UNSUPPORTED("clrex") + TEST_UNSUPPORTED("dsb") + TEST_UNSUPPORTED("dmb") + TEST_UNSUPPORTED("isb") +#endif + + verbose("\n"); +} + diff --git a/arch/arm/kernel/kprobes-test-thumb.c b/arch/arm/kernel/kprobes-test-thumb.c new file mode 100644 index 0000000000000000000000000000000000000000..5e726c31c45aef5084a7e7ddf07bb1762ed4c403 --- /dev/null +++ b/arch/arm/kernel/kprobes-test-thumb.c @@ -0,0 +1,1187 @@ +/* + * arch/arm/kernel/kprobes-test-thumb.c + * + * Copyright (C) 2011 Jon Medhurst . + * + * 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 +#include + +#include "kprobes-test.h" + + +#define TEST_ISA "16" + +#define DONT_TEST_IN_ITBLOCK(tests) \ + kprobe_test_flags |= TEST_FLAG_NO_ITBLOCK; \ + tests \ + kprobe_test_flags &= ~TEST_FLAG_NO_ITBLOCK; + +#define CONDITION_INSTRUCTIONS(cc_pos, tests) \ + kprobe_test_cc_position = cc_pos; \ + DONT_TEST_IN_ITBLOCK(tests) \ + kprobe_test_cc_position = 0; + +#define TEST_ITBLOCK(code) \ + kprobe_test_flags |= TEST_FLAG_FULL_ITBLOCK; \ + TESTCASE_START(code) \ + TEST_ARG_END("") \ + "50: nop \n\t" \ + "1: "code" \n\t" \ + " mov r1, #0x11 \n\t" \ + " mov r2, #0x22 \n\t" \ + " mov r3, #0x33 \n\t" \ + "2: nop \n\t" \ + TESTCASE_END \ + kprobe_test_flags &= ~TEST_FLAG_FULL_ITBLOCK; + +#define TEST_THUMB_TO_ARM_INTERWORK_P(code1, reg, val, code2) \ + TESTCASE_START(code1 #reg code2) \ + TEST_ARG_PTR(reg, val) \ + TEST_ARG_REG(14, 99f+1) \ + TEST_ARG_MEM(15, 3f) \ + TEST_ARG_END("") \ + " nop \n\t" /* To align 1f */ \ + "50: nop \n\t" \ + "1: "code1 #reg code2" \n\t" \ + " bx lr \n\t" \ + ".arm \n\t" \ + "3: adr lr, 2f+1 \n\t" \ + " bx lr \n\t" \ + ".thumb \n\t" \ + "2: nop \n\t" \ + TESTCASE_END + + +void kprobe_thumb16_test_cases(void) +{ + kprobe_test_flags = TEST_FLAG_NARROW_INSTR; + + TEST_GROUP("Shift (immediate), add, subtract, move, and compare") + + TEST_R( "lsls r7, r",0,VAL1,", #5") + TEST_R( "lsls r0, r",7,VAL2,", #11") + TEST_R( "lsrs r7, r",0,VAL1,", #5") + TEST_R( "lsrs r0, r",7,VAL2,", #11") + TEST_R( "asrs r7, r",0,VAL1,", #5") + TEST_R( "asrs r0, r",7,VAL2,", #11") + TEST_RR( "adds r2, r",0,VAL1,", r",7,VAL2,"") + TEST_RR( "adds r5, r",7,VAL2,", r",0,VAL2,"") + TEST_RR( "subs r2, r",0,VAL1,", r",7,VAL2,"") + TEST_RR( "subs r5, r",7,VAL2,", r",0,VAL2,"") + TEST_R( "adds r7, r",0,VAL1,", #5") + TEST_R( "adds r0, r",7,VAL2,", #2") + TEST_R( "subs r7, r",0,VAL1,", #5") + TEST_R( "subs r0, r",7,VAL2,", #2") + TEST( "movs.n r0, #0x5f") + TEST( "movs.n r7, #0xa0") + TEST_R( "cmp.n r",0,0x5e, ", #0x5f") + TEST_R( "cmp.n r",5,0x15f,", #0x5f") + TEST_R( "cmp.n r",7,0xa0, ", #0xa0") + TEST_R( "adds.n r",0,VAL1,", #0x5f") + TEST_R( "adds.n r",7,VAL2,", #0xa0") + TEST_R( "subs.n r",0,VAL1,", #0x5f") + TEST_R( "subs.n r",7,VAL2,", #0xa0") + + TEST_GROUP("16-bit Thumb data-processing instructions") + +#define DATA_PROCESSING16(op,val) \ + TEST_RR( op" r",0,VAL1,", r",7,val,"") \ + TEST_RR( op" r",7,VAL2,", r",0,val,"") + + DATA_PROCESSING16("ands",0xf00f00ff) + DATA_PROCESSING16("eors",0xf00f00ff) + DATA_PROCESSING16("lsls",11) + DATA_PROCESSING16("lsrs",11) + DATA_PROCESSING16("asrs",11) + DATA_PROCESSING16("adcs",VAL2) + DATA_PROCESSING16("sbcs",VAL2) + DATA_PROCESSING16("rors",11) + DATA_PROCESSING16("tst",0xf00f00ff) + TEST_R("rsbs r",0,VAL1,", #0") + TEST_R("rsbs r",7,VAL2,", #0") + DATA_PROCESSING16("cmp",0xf00f00ff) + DATA_PROCESSING16("cmn",0xf00f00ff) + DATA_PROCESSING16("orrs",0xf00f00ff) + DATA_PROCESSING16("muls",VAL2) + DATA_PROCESSING16("bics",0xf00f00ff) + DATA_PROCESSING16("mvns",VAL2) + + TEST_GROUP("Special data instructions and branch and exchange") + + TEST_RR( "add r",0, VAL1,", r",7,VAL2,"") + TEST_RR( "add r",3, VAL2,", r",8,VAL3,"") + TEST_RR( "add r",8, VAL3,", r",0,VAL1,"") + TEST_R( "add sp" ", r",8,-8, "") + TEST_R( "add r",14,VAL1,", pc") + TEST_BF_R("add pc" ", r",0,2f-1f-8,"") + TEST_UNSUPPORTED(".short 0x44ff @ add pc, pc") + + TEST_RR( "cmp r",3,VAL1,", r",8,VAL2,"") + TEST_RR( "cmp r",8,VAL2,", r",0,VAL1,"") + TEST_R( "cmp sp" ", r",8,-8, "") + + TEST_R( "mov r0, r",7,VAL2,"") + TEST_R( "mov r3, r",8,VAL3,"") + TEST_R( "mov r8, r",0,VAL1,"") + TEST_P( "mov sp, r",8,-8, "") + TEST( "mov lr, pc") + TEST_BF_R("mov pc, r",0,2f, "") + + TEST_BF_R("bx r",0, 2f+1,"") + TEST_BF_R("bx r",14,2f+1,"") + TESTCASE_START("bx pc") + TEST_ARG_REG(14, 99f+1) + TEST_ARG_END("") + " nop \n\t" /* To align the bx pc*/ + "50: nop \n\t" + "1: bx pc \n\t" + " bx lr \n\t" + ".arm \n\t" + " adr lr, 2f+1 \n\t" + " bx lr \n\t" + ".thumb \n\t" + "2: nop \n\t" + TESTCASE_END + + TEST_BF_R("blx r",0, 2f+1,"") + TEST_BB_R("blx r",14,2f+1,"") + TEST_UNSUPPORTED(".short 0x47f8 @ blx pc") + + TEST_GROUP("Load from Literal Pool") + + TEST_X( "ldr r0, 3f", + ".align \n\t" + "3: .word "__stringify(VAL1)) + TEST_X( "ldr r7, 3f", + ".space 128 \n\t" + ".align \n\t" + "3: .word "__stringify(VAL2)) + + TEST_GROUP("16-bit Thumb Load/store instructions") + + TEST_RPR("str r",0, VAL1,", [r",1, 24,", r",2, 48,"]") + TEST_RPR("str r",7, VAL2,", [r",6, 24,", r",5, 48,"]") + TEST_RPR("strh r",0, VAL1,", [r",1, 24,", r",2, 48,"]") + TEST_RPR("strh r",7, VAL2,", [r",6, 24,", r",5, 48,"]") + TEST_RPR("strb r",0, VAL1,", [r",1, 24,", r",2, 48,"]") + TEST_RPR("strb r",7, VAL2,", [r",6, 24,", r",5, 48,"]") + TEST_PR( "ldrsb r0, [r",1, 24,", r",2, 48,"]") + TEST_PR( "ldrsb r7, [r",6, 24,", r",5, 50,"]") + TEST_PR( "ldr r0, [r",1, 24,", r",2, 48,"]") + TEST_PR( "ldr r7, [r",6, 24,", r",5, 48,"]") + TEST_PR( "ldrh r0, [r",1, 24,", r",2, 48,"]") + TEST_PR( "ldrh r7, [r",6, 24,", r",5, 50,"]") + TEST_PR( "ldrb r0, [r",1, 24,", r",2, 48,"]") + TEST_PR( "ldrb r7, [r",6, 24,", r",5, 50,"]") + TEST_PR( "ldrsh r0, [r",1, 24,", r",2, 48,"]") + TEST_PR( "ldrsh r7, [r",6, 24,", r",5, 50,"]") + + TEST_RP("str r",0, VAL1,", [r",1, 24,", #120]") + TEST_RP("str r",7, VAL2,", [r",6, 24,", #120]") + TEST_P( "ldr r0, [r",1, 24,", #120]") + TEST_P( "ldr r7, [r",6, 24,", #120]") + TEST_RP("strb r",0, VAL1,", [r",1, 24,", #30]") + TEST_RP("strb r",7, VAL2,", [r",6, 24,", #30]") + TEST_P( "ldrb r0, [r",1, 24,", #30]") + TEST_P( "ldrb r7, [r",6, 24,", #30]") + TEST_RP("strh r",0, VAL1,", [r",1, 24,", #60]") + TEST_RP("strh r",7, VAL2,", [r",6, 24,", #60]") + TEST_P( "ldrh r0, [r",1, 24,", #60]") + TEST_P( "ldrh r7, [r",6, 24,", #60]") + + TEST_R( "str r",0, VAL1,", [sp, #0]") + TEST_R( "str r",7, VAL2,", [sp, #160]") + TEST( "ldr r0, [sp, #0]") + TEST( "ldr r7, [sp, #160]") + + TEST_RP("str r",0, VAL1,", [r",0, 24,"]") + TEST_P( "ldr r0, [r",0, 24,"]") + + TEST_GROUP("Generate PC-/SP-relative address") + + TEST("add r0, pc, #4") + TEST("add r7, pc, #1020") + TEST("add r0, sp, #4") + TEST("add r7, sp, #1020") + + TEST_GROUP("Miscellaneous 16-bit instructions") + + TEST_UNSUPPORTED( "cpsie i") + TEST_UNSUPPORTED( "cpsid i") + TEST_UNSUPPORTED( "setend le") + TEST_UNSUPPORTED( "setend be") + + TEST("add sp, #"__stringify(TEST_MEMORY_SIZE)) /* Assumes TEST_MEMORY_SIZE < 0x400 */ + TEST("sub sp, #0x7f*4") + +DONT_TEST_IN_ITBLOCK( + TEST_BF_R( "cbnz r",0,0, ", 2f") + TEST_BF_R( "cbz r",2,-1,", 2f") + TEST_BF_RX( "cbnz r",4,1, ", 2f",0x20) + TEST_BF_RX( "cbz r",7,0, ", 2f",0x40) +) + TEST_R("sxth r0, r",7, HH1,"") + TEST_R("sxth r7, r",0, HH2,"") + TEST_R("sxtb r0, r",7, HH1,"") + TEST_R("sxtb r7, r",0, HH2,"") + TEST_R("uxth r0, r",7, HH1,"") + TEST_R("uxth r7, r",0, HH2,"") + TEST_R("uxtb r0, r",7, HH1,"") + TEST_R("uxtb r7, r",0, HH2,"") + TEST_R("rev r0, r",7, VAL1,"") + TEST_R("rev r7, r",0, VAL2,"") + TEST_R("rev16 r0, r",7, VAL1,"") + TEST_R("rev16 r7, r",0, VAL2,"") + TEST_UNSUPPORTED(".short 0xba80") + TEST_UNSUPPORTED(".short 0xbabf") + TEST_R("revsh r0, r",7, VAL1,"") + TEST_R("revsh r7, r",0, VAL2,"") + +#define TEST_POPPC(code, offset) \ + TESTCASE_START(code) \ + TEST_ARG_PTR(13, offset) \ + TEST_ARG_END("") \ + TEST_BRANCH_F(code,0) \ + TESTCASE_END + + TEST("push {r0}") + TEST("push {r7}") + TEST("push {r14}") + TEST("push {r0-r7,r14}") + TEST("push {r0,r2,r4,r6,r14}") + TEST("push {r1,r3,r5,r7}") + TEST("pop {r0}") + TEST("pop {r7}") + TEST("pop {r0,r2,r4,r6}") + TEST_POPPC("pop {pc}",15*4) + TEST_POPPC("pop {r0-r7,pc}",7*4) + TEST_POPPC("pop {r1,r3,r5,r7,pc}",11*4) + TEST_THUMB_TO_ARM_INTERWORK_P("pop {pc} @ ",13,15*4,"") + TEST_THUMB_TO_ARM_INTERWORK_P("pop {r0-r7,pc} @ ",13,7*4,"") + + TEST_UNSUPPORTED("bkpt.n 0") + TEST_UNSUPPORTED("bkpt.n 255") + + TEST_SUPPORTED("yield") + TEST("sev") + TEST("nop") + TEST("wfi") + TEST_SUPPORTED("wfe") + TEST_UNSUPPORTED(".short 0xbf50") /* Unassigned hints */ + TEST_UNSUPPORTED(".short 0xbff0") /* Unassigned hints */ + +#define TEST_IT(code, code2) \ + TESTCASE_START(code) \ + TEST_ARG_END("") \ + "50: nop \n\t" \ + "1: "code" \n\t" \ + " "code2" \n\t" \ + "2: nop \n\t" \ + TESTCASE_END + +DONT_TEST_IN_ITBLOCK( + TEST_IT("it eq","moveq r0,#0") + TEST_IT("it vc","movvc r0,#0") + TEST_IT("it le","movle r0,#0") + TEST_IT("ite eq","moveq r0,#0\n\t movne r1,#1") + TEST_IT("itet vc","movvc r0,#0\n\t movvs r1,#1\n\t movvc r2,#2") + TEST_IT("itete le","movle r0,#0\n\t movgt r1,#1\n\t movle r2,#2\n\t movgt r3,#3") + TEST_IT("itttt le","movle r0,#0\n\t movle r1,#1\n\t movle r2,#2\n\t movle r3,#3") + TEST_IT("iteee le","movle r0,#0\n\t movgt r1,#1\n\t movgt r2,#2\n\t movgt r3,#3") +) + + TEST_GROUP("Load and store multiple") + + TEST_P("ldmia r",4, 16*4,"!, {r0,r7}") + TEST_P("ldmia r",7, 16*4,"!, {r0-r6}") + TEST_P("stmia r",4, 16*4,"!, {r0,r7}") + TEST_P("stmia r",0, 16*4,"!, {r0-r7}") + + TEST_GROUP("Conditional branch and Supervisor Call instructions") + +CONDITION_INSTRUCTIONS(8, + TEST_BF("beq 2f") + TEST_BB("bne 2b") + TEST_BF("bgt 2f") + TEST_BB("blt 2b") +) + TEST_UNSUPPORTED(".short 0xde00") + TEST_UNSUPPORTED(".short 0xdeff") + TEST_UNSUPPORTED("svc #0x00") + TEST_UNSUPPORTED("svc #0xff") + + TEST_GROUP("Unconditional branch") + + TEST_BF( "b 2f") + TEST_BB( "b 2b") + TEST_BF_X("b 2f", 0x400) + TEST_BB_X("b 2b", 0x400) + + TEST_GROUP("Testing instructions in IT blocks") + + TEST_ITBLOCK("subs.n r0, r0") + + verbose("\n"); +} + + +void kprobe_thumb32_test_cases(void) +{ + kprobe_test_flags = 0; + + TEST_GROUP("Load/store multiple") + + TEST_UNSUPPORTED("rfedb sp") + TEST_UNSUPPORTED("rfeia sp") + TEST_UNSUPPORTED("rfedb sp!") + TEST_UNSUPPORTED("rfeia sp!") + + TEST_P( "stmia r",0, 16*4,", {r0,r8}") + TEST_P( "stmia r",4, 16*4,", {r0-r12,r14}") + TEST_P( "stmia r",7, 16*4,"!, {r8-r12,r14}") + TEST_P( "stmia r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}") + + TEST_P( "ldmia r",0, 16*4,", {r0,r8}") + TEST_P( "ldmia r",4, 0, ", {r0-r12,r14}") + TEST_BF_P("ldmia r",5, 8*4, "!, {r6-r12,r15}") + TEST_P( "ldmia r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}") + TEST_BF_P("ldmia r",14,14*4,"!, {r4,pc}") + + TEST_P( "stmdb r",0, 16*4,", {r0,r8}") + TEST_P( "stmdb r",4, 16*4,", {r0-r12,r14}") + TEST_P( "stmdb r",5, 16*4,"!, {r8-r12,r14}") + TEST_P( "stmdb r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}") + + TEST_P( "ldmdb r",0, 16*4,", {r0,r8}") + TEST_P( "ldmdb r",4, 16*4,", {r0-r12,r14}") + TEST_BF_P("ldmdb r",5, 16*4,"!, {r6-r12,r15}") + TEST_P( "ldmdb r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}") + TEST_BF_P("ldmdb r",14,16*4,"!, {r4,pc}") + + TEST_P( "stmdb r",13,16*4,"!, {r3-r12,lr}") + TEST_P( "stmdb r",13,16*4,"!, {r3-r12}") + TEST_P( "stmdb r",2, 16*4,", {r3-r12,lr}") + TEST_P( "stmdb r",13,16*4,"!, {r2-r12,lr}") + TEST_P( "stmdb r",0, 16*4,", {r0-r12}") + TEST_P( "stmdb r",0, 16*4,", {r0-r12,lr}") + + TEST_BF_P("ldmia r",13,5*4, "!, {r3-r12,pc}") + TEST_P( "ldmia r",13,5*4, "!, {r3-r12}") + TEST_BF_P("ldmia r",2, 5*4, "!, {r3-r12,pc}") + TEST_BF_P("ldmia r",13,4*4, "!, {r2-r12,pc}") + TEST_P( "ldmia r",0, 16*4,", {r0-r12}") + TEST_P( "ldmia r",0, 16*4,", {r0-r12,lr}") + + TEST_THUMB_TO_ARM_INTERWORK_P("ldmia r",0,14*4,", {r12,pc}") + TEST_THUMB_TO_ARM_INTERWORK_P("ldmia r",13,2*4,", {r0-r12,pc}") + + TEST_UNSUPPORTED(".short 0xe88f,0x0101 @ stmia pc, {r0,r8}") + TEST_UNSUPPORTED(".short 0xe92f,0x5f00 @ stmdb pc!, {r8-r12,r14}") + TEST_UNSUPPORTED(".short 0xe8bd,0xc000 @ ldmia r13!, {r14,pc}") + TEST_UNSUPPORTED(".short 0xe93e,0xc000 @ ldmdb r14!, {r14,pc}") + TEST_UNSUPPORTED(".short 0xe8a7,0x3f00 @ stmia r7!, {r8-r12,sp}") + TEST_UNSUPPORTED(".short 0xe8a7,0x9f00 @ stmia r7!, {r8-r12,pc}") + TEST_UNSUPPORTED(".short 0xe93e,0x2010 @ ldmdb r14!, {r4,sp}") + + TEST_GROUP("Load/store double or exclusive, table branch") + + TEST_P( "ldrd r0, r1, [r",1, 24,", #-16]") + TEST( "ldrd r12, r14, [sp, #16]") + TEST_P( "ldrd r1, r0, [r",7, 24,", #-16]!") + TEST( "ldrd r14, r12, [sp, #16]!") + TEST_P( "ldrd r1, r0, [r",7, 24,"], #16") + TEST( "ldrd r7, r8, [sp], #-16") + + TEST_X( "ldrd r12, r14, 3f", + ".align 3 \n\t" + "3: .word "__stringify(VAL1)" \n\t" + " .word "__stringify(VAL2)) + + TEST_UNSUPPORTED(".short 0xe9ff,0xec04 @ ldrd r14, r12, [pc, #16]!") + TEST_UNSUPPORTED(".short 0xe8ff,0xec04 @ ldrd r14, r12, [pc], #16") + TEST_UNSUPPORTED(".short 0xe9d4,0xd800 @ ldrd sp, r8, [r4]") + TEST_UNSUPPORTED(".short 0xe9d4,0xf800 @ ldrd pc, r8, [r4]") + TEST_UNSUPPORTED(".short 0xe9d4,0x7d00 @ ldrd r7, sp, [r4]") + TEST_UNSUPPORTED(".short 0xe9d4,0x7f00 @ ldrd r7, pc, [r4]") + + TEST_RRP("strd r",0, VAL1,", r",1, VAL2,", [r",1, 24,", #-16]") + TEST_RR( "strd r",12,VAL2,", r",14,VAL1,", [sp, #16]") + TEST_RRP("strd r",1, VAL1,", r",0, VAL2,", [r",7, 24,", #-16]!") + TEST_RR( "strd r",14,VAL2,", r",12,VAL1,", [sp, #16]!") + TEST_RRP("strd r",1, VAL1,", r",0, VAL2,", [r",7, 24,"], #16") + TEST_RR( "strd r",7, VAL2,", r",8, VAL1,", [sp], #-16") + TEST_UNSUPPORTED(".short 0xe9ef,0xec04 @ strd r14, r12, [pc, #16]!") + TEST_UNSUPPORTED(".short 0xe8ef,0xec04 @ strd r14, r12, [pc], #16") + + TEST_RX("tbb [pc, r",0, (9f-(1f+4)),"]", + "9: \n\t" + ".byte (2f-1b-4)>>1 \n\t" + ".byte (3f-1b-4)>>1 \n\t" + "3: mvn r0, r0 \n\t" + "2: nop \n\t") + + TEST_RX("tbb [pc, r",4, (9f-(1f+4)+1),"]", + "9: \n\t" + ".byte (2f-1b-4)>>1 \n\t" + ".byte (3f-1b-4)>>1 \n\t" + "3: mvn r0, r0 \n\t" + "2: nop \n\t") + + TEST_RRX("tbb [r",1,9f,", r",2,0,"]", + "9: \n\t" + ".byte (2f-1b-4)>>1 \n\t" + ".byte (3f-1b-4)>>1 \n\t" + "3: mvn r0, r0 \n\t" + "2: nop \n\t") + + TEST_RX("tbh [pc, r",7, (9f-(1f+4))>>1,"]", + "9: \n\t" + ".short (2f-1b-4)>>1 \n\t" + ".short (3f-1b-4)>>1 \n\t" + "3: mvn r0, r0 \n\t" + "2: nop \n\t") + + TEST_RX("tbh [pc, r",12, ((9f-(1f+4))>>1)+1,"]", + "9: \n\t" + ".short (2f-1b-4)>>1 \n\t" + ".short (3f-1b-4)>>1 \n\t" + "3: mvn r0, r0 \n\t" + "2: nop \n\t") + + TEST_RRX("tbh [r",1,9f, ", r",14,1,"]", + "9: \n\t" + ".short (2f-1b-4)>>1 \n\t" + ".short (3f-1b-4)>>1 \n\t" + "3: mvn r0, r0 \n\t" + "2: nop \n\t") + + TEST_UNSUPPORTED(".short 0xe8d1,0xf01f @ tbh [r1, pc]") + TEST_UNSUPPORTED(".short 0xe8d1,0xf01d @ tbh [r1, sp]") + TEST_UNSUPPORTED(".short 0xe8dd,0xf012 @ tbh [sp, r2]") + + TEST_UNSUPPORTED("strexb r0, r1, [r2]") + TEST_UNSUPPORTED("strexh r0, r1, [r2]") + TEST_UNSUPPORTED("strexd r0, r1, [r2]") + TEST_UNSUPPORTED("ldrexb r0, [r1]") + TEST_UNSUPPORTED("ldrexh r0, [r1]") + TEST_UNSUPPORTED("ldrexd r0, [r1]") + + TEST_GROUP("Data-processing (shifted register) and (modified immediate)") + +#define _DATA_PROCESSING32_DNM(op,s,val) \ + TEST_RR(op s".w r0, r",1, VAL1,", r",2, val, "") \ + TEST_RR(op s" r1, r",1, VAL1,", r",2, val, ", lsl #3") \ + TEST_RR(op s" r2, r",3, VAL1,", r",2, val, ", lsr #4") \ + TEST_RR(op s" r3, r",3, VAL1,", r",2, val, ", asr #5") \ + TEST_RR(op s" r4, r",5, VAL1,", r",2, N(val),", asr #6") \ + TEST_RR(op s" r5, r",5, VAL1,", r",2, val, ", ror #7") \ + TEST_RR(op s" r8, r",9, VAL1,", r",10,val, ", rrx") \ + TEST_R( op s" r0, r",11,VAL1,", #0x00010001") \ + TEST_R( op s" r11, r",0, VAL1,", #0xf5000000") \ + TEST_R( op s" r7, r",8, VAL2,", #0x000af000") + +#define DATA_PROCESSING32_DNM(op,val) \ + _DATA_PROCESSING32_DNM(op,"",val) \ + _DATA_PROCESSING32_DNM(op,"s",val) + +#define DATA_PROCESSING32_NM(op,val) \ + TEST_RR(op".w r",1, VAL1,", r",2, val, "") \ + TEST_RR(op" r",1, VAL1,", r",2, val, ", lsl #3") \ + TEST_RR(op" r",3, VAL1,", r",2, val, ", lsr #4") \ + TEST_RR(op" r",3, VAL1,", r",2, val, ", asr #5") \ + TEST_RR(op" r",5, VAL1,", r",2, N(val),", asr #6") \ + TEST_RR(op" r",5, VAL1,", r",2, val, ", ror #7") \ + TEST_RR(op" r",9, VAL1,", r",10,val, ", rrx") \ + TEST_R( op" r",11,VAL1,", #0x00010001") \ + TEST_R( op" r",0, VAL1,", #0xf5000000") \ + TEST_R( op" r",8, VAL2,", #0x000af000") + +#define _DATA_PROCESSING32_DM(op,s,val) \ + TEST_R( op s".w r0, r",14, val, "") \ + TEST_R( op s" r1, r",12, val, ", lsl #3") \ + TEST_R( op s" r2, r",11, val, ", lsr #4") \ + TEST_R( op s" r3, r",10, val, ", asr #5") \ + TEST_R( op s" r4, r",9, N(val),", asr #6") \ + TEST_R( op s" r5, r",8, val, ", ror #7") \ + TEST_R( op s" r8, r",7,val, ", rrx") \ + TEST( op s" r0, #0x00010001") \ + TEST( op s" r11, #0xf5000000") \ + TEST( op s" r7, #0x000af000") \ + TEST( op s" r4, #0x00005a00") + +#define DATA_PROCESSING32_DM(op,val) \ + _DATA_PROCESSING32_DM(op,"",val) \ + _DATA_PROCESSING32_DM(op,"s",val) + + DATA_PROCESSING32_DNM("and",0xf00f00ff) + DATA_PROCESSING32_NM("tst",0xf00f00ff) + DATA_PROCESSING32_DNM("bic",0xf00f00ff) + DATA_PROCESSING32_DNM("orr",0xf00f00ff) + DATA_PROCESSING32_DM("mov",VAL2) + DATA_PROCESSING32_DNM("orn",0xf00f00ff) + DATA_PROCESSING32_DM("mvn",VAL2) + DATA_PROCESSING32_DNM("eor",0xf00f00ff) + DATA_PROCESSING32_NM("teq",0xf00f00ff) + DATA_PROCESSING32_DNM("add",VAL2) + DATA_PROCESSING32_NM("cmn",VAL2) + DATA_PROCESSING32_DNM("adc",VAL2) + DATA_PROCESSING32_DNM("sbc",VAL2) + DATA_PROCESSING32_DNM("sub",VAL2) + DATA_PROCESSING32_NM("cmp",VAL2) + DATA_PROCESSING32_DNM("rsb",VAL2) + + TEST_RR("pkhbt r0, r",0, HH1,", r",1, HH2,"") + TEST_RR("pkhbt r14,r",12, HH1,", r",10,HH2,", lsl #2") + TEST_RR("pkhtb r0, r",0, HH1,", r",1, HH2,"") + TEST_RR("pkhtb r14,r",12, HH1,", r",10,HH2,", asr #2") + + TEST_UNSUPPORTED(".short 0xea17,0x0f0d @ tst.w r7, sp") + TEST_UNSUPPORTED(".short 0xea17,0x0f0f @ tst.w r7, pc") + TEST_UNSUPPORTED(".short 0xea1d,0x0f07 @ tst.w sp, r7") + TEST_UNSUPPORTED(".short 0xea1f,0x0f07 @ tst.w pc, r7") + TEST_UNSUPPORTED(".short 0xf01d,0x1f08 @ tst sp, #0x00080008") + TEST_UNSUPPORTED(".short 0xf01f,0x1f08 @ tst pc, #0x00080008") + + TEST_UNSUPPORTED(".short 0xea97,0x0f0d @ teq.w r7, sp") + TEST_UNSUPPORTED(".short 0xea97,0x0f0f @ teq.w r7, pc") + TEST_UNSUPPORTED(".short 0xea9d,0x0f07 @ teq.w sp, r7") + TEST_UNSUPPORTED(".short 0xea9f,0x0f07 @ teq.w pc, r7") + TEST_UNSUPPORTED(".short 0xf09d,0x1f08 @ tst sp, #0x00080008") + TEST_UNSUPPORTED(".short 0xf09f,0x1f08 @ tst pc, #0x00080008") + + TEST_UNSUPPORTED(".short 0xeb17,0x0f0d @ cmn.w r7, sp") + TEST_UNSUPPORTED(".short 0xeb17,0x0f0f @ cmn.w r7, pc") + TEST_P("cmn.w sp, r",7,0,"") + TEST_UNSUPPORTED(".short 0xeb1f,0x0f07 @ cmn.w pc, r7") + TEST( "cmn sp, #0x00080008") + TEST_UNSUPPORTED(".short 0xf11f,0x1f08 @ cmn pc, #0x00080008") + + TEST_UNSUPPORTED(".short 0xebb7,0x0f0d @ cmp.w r7, sp") + TEST_UNSUPPORTED(".short 0xebb7,0x0f0f @ cmp.w r7, pc") + TEST_P("cmp.w sp, r",7,0,"") + TEST_UNSUPPORTED(".short 0xebbf,0x0f07 @ cmp.w pc, r7") + TEST( "cmp sp, #0x00080008") + TEST_UNSUPPORTED(".short 0xf1bf,0x1f08 @ cmp pc, #0x00080008") + + TEST_UNSUPPORTED(".short 0xea5f,0x070d @ movs.w r7, sp") + TEST_UNSUPPORTED(".short 0xea5f,0x070f @ movs.w r7, pc") + TEST_UNSUPPORTED(".short 0xea5f,0x0d07 @ movs.w sp, r7") + TEST_UNSUPPORTED(".short 0xea4f,0x0f07 @ mov.w pc, r7") + TEST_UNSUPPORTED(".short 0xf04f,0x1d08 @ mov sp, #0x00080008") + TEST_UNSUPPORTED(".short 0xf04f,0x1f08 @ mov pc, #0x00080008") + + TEST_R("add.w r0, sp, r",1, 4,"") + TEST_R("adds r0, sp, r",1, 4,", asl #3") + TEST_R("add r0, sp, r",1, 4,", asl #4") + TEST_R("add r0, sp, r",1, 16,", ror #1") + TEST_R("add.w sp, sp, r",1, 4,"") + TEST_R("add sp, sp, r",1, 4,", asl #3") + TEST_UNSUPPORTED(".short 0xeb0d,0x1d01 @ add sp, sp, r1, asl #4") + TEST_UNSUPPORTED(".short 0xeb0d,0x0d71 @ add sp, sp, r1, ror #1") + TEST( "add.w r0, sp, #24") + TEST( "add.w sp, sp, #24") + TEST_UNSUPPORTED(".short 0xeb0d,0x0f01 @ add pc, sp, r1") + TEST_UNSUPPORTED(".short 0xeb0d,0x000f @ add r0, sp, pc") + TEST_UNSUPPORTED(".short 0xeb0d,0x000d @ add r0, sp, sp") + TEST_UNSUPPORTED(".short 0xeb0d,0x0d0f @ add sp, sp, pc") + TEST_UNSUPPORTED(".short 0xeb0d,0x0d0d @ add sp, sp, sp") + + TEST_R("sub.w r0, sp, r",1, 4,"") + TEST_R("subs r0, sp, r",1, 4,", asl #3") + TEST_R("sub r0, sp, r",1, 4,", asl #4") + TEST_R("sub r0, sp, r",1, 16,", ror #1") + TEST_R("sub.w sp, sp, r",1, 4,"") + TEST_R("sub sp, sp, r",1, 4,", asl #3") + TEST_UNSUPPORTED(".short 0xebad,0x1d01 @ sub sp, sp, r1, asl #4") + TEST_UNSUPPORTED(".short 0xebad,0x0d71 @ sub sp, sp, r1, ror #1") + TEST_UNSUPPORTED(".short 0xebad,0x0f01 @ sub pc, sp, r1") + TEST( "sub.w r0, sp, #24") + TEST( "sub.w sp, sp, #24") + + TEST_UNSUPPORTED(".short 0xea02,0x010f @ and r1, r2, pc") + TEST_UNSUPPORTED(".short 0xea0f,0x0103 @ and r1, pc, r3") + TEST_UNSUPPORTED(".short 0xea02,0x0f03 @ and pc, r2, r3") + TEST_UNSUPPORTED(".short 0xea02,0x010d @ and r1, r2, sp") + TEST_UNSUPPORTED(".short 0xea0d,0x0103 @ and r1, sp, r3") + TEST_UNSUPPORTED(".short 0xea02,0x0d03 @ and sp, r2, r3") + TEST_UNSUPPORTED(".short 0xf00d,0x1108 @ and r1, sp, #0x00080008") + TEST_UNSUPPORTED(".short 0xf00f,0x1108 @ and r1, pc, #0x00080008") + TEST_UNSUPPORTED(".short 0xf002,0x1d08 @ and sp, r8, #0x00080008") + TEST_UNSUPPORTED(".short 0xf002,0x1f08 @ and pc, r8, #0x00080008") + + TEST_UNSUPPORTED(".short 0xeb02,0x010f @ add r1, r2, pc") + TEST_UNSUPPORTED(".short 0xeb0f,0x0103 @ add r1, pc, r3") + TEST_UNSUPPORTED(".short 0xeb02,0x0f03 @ add pc, r2, r3") + TEST_UNSUPPORTED(".short 0xeb02,0x010d @ add r1, r2, sp") + TEST_SUPPORTED( ".short 0xeb0d,0x0103 @ add r1, sp, r3") + TEST_UNSUPPORTED(".short 0xeb02,0x0d03 @ add sp, r2, r3") + TEST_SUPPORTED( ".short 0xf10d,0x1108 @ add r1, sp, #0x00080008") + TEST_UNSUPPORTED(".short 0xf10d,0x1f08 @ add pc, sp, #0x00080008") + TEST_UNSUPPORTED(".short 0xf10f,0x1108 @ add r1, pc, #0x00080008") + TEST_UNSUPPORTED(".short 0xf102,0x1d08 @ add sp, r8, #0x00080008") + TEST_UNSUPPORTED(".short 0xf102,0x1f08 @ add pc, r8, #0x00080008") + + TEST_UNSUPPORTED(".short 0xeaa0,0x0000") + TEST_UNSUPPORTED(".short 0xeaf0,0x0000") + TEST_UNSUPPORTED(".short 0xeb20,0x0000") + TEST_UNSUPPORTED(".short 0xeb80,0x0000") + TEST_UNSUPPORTED(".short 0xebe0,0x0000") + + TEST_UNSUPPORTED(".short 0xf0a0,0x0000") + TEST_UNSUPPORTED(".short 0xf0c0,0x0000") + TEST_UNSUPPORTED(".short 0xf0f0,0x0000") + TEST_UNSUPPORTED(".short 0xf120,0x0000") + TEST_UNSUPPORTED(".short 0xf180,0x0000") + TEST_UNSUPPORTED(".short 0xf1e0,0x0000") + + TEST_GROUP("Coprocessor instructions") + + TEST_UNSUPPORTED(".short 0xec00,0x0000") + TEST_UNSUPPORTED(".short 0xeff0,0x0000") + TEST_UNSUPPORTED(".short 0xfc00,0x0000") + TEST_UNSUPPORTED(".short 0xfff0,0x0000") + + TEST_GROUP("Data-processing (plain binary immediate)") + + TEST_R("addw r0, r",1, VAL1,", #0x123") + TEST( "addw r14, sp, #0xf5a") + TEST( "addw sp, sp, #0x20") + TEST( "addw r7, pc, #0x888") + TEST_UNSUPPORTED(".short 0xf20f,0x1f20 @ addw pc, pc, #0x120") + TEST_UNSUPPORTED(".short 0xf20d,0x1f20 @ addw pc, sp, #0x120") + TEST_UNSUPPORTED(".short 0xf20f,0x1d20 @ addw sp, pc, #0x120") + TEST_UNSUPPORTED(".short 0xf200,0x1d20 @ addw sp, r0, #0x120") + + TEST_R("subw r0, r",1, VAL1,", #0x123") + TEST( "subw r14, sp, #0xf5a") + TEST( "subw sp, sp, #0x20") + TEST( "subw r7, pc, #0x888") + TEST_UNSUPPORTED(".short 0xf2af,0x1f20 @ subw pc, pc, #0x120") + TEST_UNSUPPORTED(".short 0xf2ad,0x1f20 @ subw pc, sp, #0x120") + TEST_UNSUPPORTED(".short 0xf2af,0x1d20 @ subw sp, pc, #0x120") + TEST_UNSUPPORTED(".short 0xf2a0,0x1d20 @ subw sp, r0, #0x120") + + TEST("movw r0, #0") + TEST("movw r0, #0xffff") + TEST("movw lr, #0xffff") + TEST_UNSUPPORTED(".short 0xf240,0x0d00 @ movw sp, #0") + TEST_UNSUPPORTED(".short 0xf240,0x0f00 @ movw pc, #0") + + TEST_R("movt r",0, VAL1,", #0") + TEST_R("movt r",0, VAL2,", #0xffff") + TEST_R("movt r",14,VAL1,", #0xffff") + TEST_UNSUPPORTED(".short 0xf2c0,0x0d00 @ movt sp, #0") + TEST_UNSUPPORTED(".short 0xf2c0,0x0f00 @ movt pc, #0") + + TEST_R( "ssat r0, #24, r",0, VAL1,"") + TEST_R( "ssat r14, #24, r",12, VAL2,"") + TEST_R( "ssat r0, #24, r",0, VAL1,", lsl #8") + TEST_R( "ssat r14, #24, r",12, VAL2,", asr #8") + TEST_UNSUPPORTED(".short 0xf30c,0x0d17 @ ssat sp, #24, r12") + TEST_UNSUPPORTED(".short 0xf30c,0x0f17 @ ssat pc, #24, r12") + TEST_UNSUPPORTED(".short 0xf30d,0x0c17 @ ssat r12, #24, sp") + TEST_UNSUPPORTED(".short 0xf30f,0x0c17 @ ssat r12, #24, pc") + + TEST_R( "usat r0, #24, r",0, VAL1,"") + TEST_R( "usat r14, #24, r",12, VAL2,"") + TEST_R( "usat r0, #24, r",0, VAL1,", lsl #8") + TEST_R( "usat r14, #24, r",12, VAL2,", asr #8") + TEST_UNSUPPORTED(".short 0xf38c,0x0d17 @ usat sp, #24, r12") + TEST_UNSUPPORTED(".short 0xf38c,0x0f17 @ usat pc, #24, r12") + TEST_UNSUPPORTED(".short 0xf38d,0x0c17 @ usat r12, #24, sp") + TEST_UNSUPPORTED(".short 0xf38f,0x0c17 @ usat r12, #24, pc") + + TEST_R( "ssat16 r0, #12, r",0, HH1,"") + TEST_R( "ssat16 r14, #12, r",12, HH2,"") + TEST_UNSUPPORTED(".short 0xf32c,0x0d0b @ ssat16 sp, #12, r12") + TEST_UNSUPPORTED(".short 0xf32c,0x0f0b @ ssat16 pc, #12, r12") + TEST_UNSUPPORTED(".short 0xf32d,0x0c0b @ ssat16 r12, #12, sp") + TEST_UNSUPPORTED(".short 0xf32f,0x0c0b @ ssat16 r12, #12, pc") + + TEST_R( "usat16 r0, #12, r",0, HH1,"") + TEST_R( "usat16 r14, #12, r",12, HH2,"") + TEST_UNSUPPORTED(".short 0xf3ac,0x0d0b @ usat16 sp, #12, r12") + TEST_UNSUPPORTED(".short 0xf3ac,0x0f0b @ usat16 pc, #12, r12") + TEST_UNSUPPORTED(".short 0xf3ad,0x0c0b @ usat16 r12, #12, sp") + TEST_UNSUPPORTED(".short 0xf3af,0x0c0b @ usat16 r12, #12, pc") + + TEST_R( "sbfx r0, r",0 , VAL1,", #0, #31") + TEST_R( "sbfx r14, r",12, VAL2,", #8, #16") + TEST_R( "sbfx r4, r",10, VAL1,", #16, #15") + TEST_UNSUPPORTED(".short 0xf34c,0x2d0f @ sbfx sp, r12, #8, #16") + TEST_UNSUPPORTED(".short 0xf34c,0x2f0f @ sbfx pc, r12, #8, #16") + TEST_UNSUPPORTED(".short 0xf34d,0x2c0f @ sbfx r12, sp, #8, #16") + TEST_UNSUPPORTED(".short 0xf34f,0x2c0f @ sbfx r12, pc, #8, #16") + + TEST_R( "ubfx r0, r",0 , VAL1,", #0, #31") + TEST_R( "ubfx r14, r",12, VAL2,", #8, #16") + TEST_R( "ubfx r4, r",10, VAL1,", #16, #15") + TEST_UNSUPPORTED(".short 0xf3cc,0x2d0f @ ubfx sp, r12, #8, #16") + TEST_UNSUPPORTED(".short 0xf3cc,0x2f0f @ ubfx pc, r12, #8, #16") + TEST_UNSUPPORTED(".short 0xf3cd,0x2c0f @ ubfx r12, sp, #8, #16") + TEST_UNSUPPORTED(".short 0xf3cf,0x2c0f @ ubfx r12, pc, #8, #16") + + TEST_R( "bfc r",0, VAL1,", #4, #20") + TEST_R( "bfc r",14,VAL2,", #4, #20") + TEST_R( "bfc r",7, VAL1,", #0, #31") + TEST_R( "bfc r",8, VAL2,", #0, #31") + TEST_UNSUPPORTED(".short 0xf36f,0x0d1e @ bfc sp, #0, #31") + TEST_UNSUPPORTED(".short 0xf36f,0x0f1e @ bfc pc, #0, #31") + + TEST_RR( "bfi r",0, VAL1,", r",0 , VAL2,", #0, #31") + TEST_RR( "bfi r",12,VAL1,", r",14 , VAL2,", #4, #20") + TEST_UNSUPPORTED(".short 0xf36e,0x1d17 @ bfi sp, r14, #4, #20") + TEST_UNSUPPORTED(".short 0xf36e,0x1f17 @ bfi pc, r14, #4, #20") + TEST_UNSUPPORTED(".short 0xf36d,0x1e17 @ bfi r14, sp, #4, #20") + + TEST_GROUP("Branches and miscellaneous control") + +CONDITION_INSTRUCTIONS(22, + TEST_BF("beq.w 2f") + TEST_BB("bne.w 2b") + TEST_BF("bgt.w 2f") + TEST_BB("blt.w 2b") + TEST_BF_X("bpl.w 2f",0x1000) +) + + TEST_UNSUPPORTED("msr cpsr, r0") + TEST_UNSUPPORTED("msr cpsr_f, r1") + TEST_UNSUPPORTED("msr spsr, r2") + + TEST_UNSUPPORTED("cpsie.w i") + TEST_UNSUPPORTED("cpsid.w i") + TEST_UNSUPPORTED("cps 0x13") + + TEST_SUPPORTED("yield.w") + TEST("sev.w") + TEST("nop.w") + TEST("wfi.w") + TEST_SUPPORTED("wfe.w") + TEST_UNSUPPORTED("dbg.w #0") + + TEST_UNSUPPORTED("clrex") + TEST_UNSUPPORTED("dsb") + TEST_UNSUPPORTED("dmb") + TEST_UNSUPPORTED("isb") + + TEST_UNSUPPORTED("bxj r0") + + TEST_UNSUPPORTED("subs pc, lr, #4") + + TEST("mrs r0, cpsr") + TEST("mrs r14, cpsr") + TEST_UNSUPPORTED(".short 0xf3ef,0x8d00 @ mrs sp, spsr") + TEST_UNSUPPORTED(".short 0xf3ef,0x8f00 @ mrs pc, spsr") + TEST_UNSUPPORTED("mrs r0, spsr") + TEST_UNSUPPORTED("mrs lr, spsr") + + TEST_UNSUPPORTED(".short 0xf7f0,0x8000 @ smc #0") + + TEST_UNSUPPORTED(".short 0xf7f0,0xa000 @ undefeined") + + TEST_BF( "b.w 2f") + TEST_BB( "b.w 2b") + TEST_BF_X("b.w 2f", 0x1000) + + TEST_BF( "bl.w 2f") + TEST_BB( "bl.w 2b") + TEST_BB_X("bl.w 2b", 0x1000) + + TEST_X( "blx __dummy_arm_subroutine", + ".arm \n\t" + ".align \n\t" + ".type __dummy_arm_subroutine, %%function \n\t" + "__dummy_arm_subroutine: \n\t" + "mov r0, pc \n\t" + "bx lr \n\t" + ".thumb \n\t" + ) + TEST( "blx __dummy_arm_subroutine") + + TEST_GROUP("Store single data item") + +#define SINGLE_STORE(size) \ + TEST_RP( "str"size" r",0, VAL1,", [r",11,-1024,", #1024]") \ + TEST_RP( "str"size" r",14,VAL2,", [r",1, -1024,", #1080]") \ + TEST_RP( "str"size" r",0, VAL1,", [r",11,256, ", #-120]") \ + TEST_RP( "str"size" r",14,VAL2,", [r",1, 256, ", #-128]") \ + TEST_RP( "str"size" r",0, VAL1,", [r",11,24, "], #120") \ + TEST_RP( "str"size" r",14,VAL2,", [r",1, 24, "], #128") \ + TEST_RP( "str"size" r",0, VAL1,", [r",11,24, "], #-120") \ + TEST_RP( "str"size" r",14,VAL2,", [r",1, 24, "], #-128") \ + TEST_RP( "str"size" r",0, VAL1,", [r",11,24, ", #120]!") \ + TEST_RP( "str"size" r",14,VAL2,", [r",1, 24, ", #128]!") \ + TEST_RP( "str"size" r",0, VAL1,", [r",11,256, ", #-120]!") \ + TEST_RP( "str"size" r",14,VAL2,", [r",1, 256, ", #-128]!") \ + TEST_RPR("str"size".w r",0, VAL1,", [r",1, 0,", r",2, 4,"]") \ + TEST_RPR("str"size" r",14,VAL2,", [r",10,0,", r",11,4,", lsl #1]") \ + TEST_R( "str"size".w r",7, VAL1,", [sp, #24]") \ + TEST_RP( "str"size".w r",0, VAL2,", [r",0,0, "]") \ + TEST_UNSUPPORTED("str"size"t r0, [r1, #4]") + + SINGLE_STORE("b") + SINGLE_STORE("h") + SINGLE_STORE("") + + TEST("str sp, [sp]") + TEST_UNSUPPORTED(".short 0xf8cf,0xe000 @ str r14, [pc]") + TEST_UNSUPPORTED(".short 0xf8ce,0xf000 @ str pc, [r14]") + + TEST_GROUP("Advanced SIMD element or structure load/store instructions") + + TEST_UNSUPPORTED(".short 0xf900,0x0000") + TEST_UNSUPPORTED(".short 0xf92f,0xffff") + TEST_UNSUPPORTED(".short 0xf980,0x0000") + TEST_UNSUPPORTED(".short 0xf9ef,0xffff") + + TEST_GROUP("Load single data item and memory hints") + +#define SINGLE_LOAD(size) \ + TEST_P( "ldr"size" r0, [r",11,-1024, ", #1024]") \ + TEST_P( "ldr"size" r14, [r",1, -1024,", #1080]") \ + TEST_P( "ldr"size" r0, [r",11,256, ", #-120]") \ + TEST_P( "ldr"size" r14, [r",1, 256, ", #-128]") \ + TEST_P( "ldr"size" r0, [r",11,24, "], #120") \ + TEST_P( "ldr"size" r14, [r",1, 24, "], #128") \ + TEST_P( "ldr"size" r0, [r",11,24, "], #-120") \ + TEST_P( "ldr"size" r14, [r",1,24, "], #-128") \ + TEST_P( "ldr"size" r0, [r",11,24, ", #120]!") \ + TEST_P( "ldr"size" r14, [r",1, 24, ", #128]!") \ + TEST_P( "ldr"size" r0, [r",11,256, ", #-120]!") \ + TEST_P( "ldr"size" r14, [r",1, 256, ", #-128]!") \ + TEST_PR("ldr"size".w r0, [r",1, 0,", r",2, 4,"]") \ + TEST_PR("ldr"size" r14, [r",10,0,", r",11,4,", lsl #1]") \ + TEST_X( "ldr"size".w r0, 3f", \ + ".align 3 \n\t" \ + "3: .word "__stringify(VAL1)) \ + TEST_X( "ldr"size".w r14, 3f", \ + ".align 3 \n\t" \ + "3: .word "__stringify(VAL2)) \ + TEST( "ldr"size".w r7, 3b") \ + TEST( "ldr"size".w r7, [sp, #24]") \ + TEST_P( "ldr"size".w r0, [r",0,0, "]") \ + TEST_UNSUPPORTED("ldr"size"t r0, [r1, #4]") + + SINGLE_LOAD("b") + SINGLE_LOAD("sb") + SINGLE_LOAD("h") + SINGLE_LOAD("sh") + SINGLE_LOAD("") + + TEST_BF_P("ldr pc, [r",14, 15*4,"]") + TEST_P( "ldr sp, [r",14, 13*4,"]") + TEST_BF_R("ldr pc, [sp, r",14, 15*4,"]") + TEST_R( "ldr sp, [sp, r",14, 13*4,"]") + TEST_THUMB_TO_ARM_INTERWORK_P("ldr pc, [r",0,0,", #15*4]") + TEST_SUPPORTED("ldr sp, 99f") + TEST_SUPPORTED("ldr pc, 99f") + + TEST_UNSUPPORTED(".short 0xf854,0x700d @ ldr r7, [r4, sp]") + TEST_UNSUPPORTED(".short 0xf854,0x700f @ ldr r7, [r4, pc]") + TEST_UNSUPPORTED(".short 0xf814,0x700d @ ldrb r7, [r4, sp]") + TEST_UNSUPPORTED(".short 0xf814,0x700f @ ldrb r7, [r4, pc]") + TEST_UNSUPPORTED(".short 0xf89f,0xd004 @ ldrb sp, 99f") + TEST_UNSUPPORTED(".short 0xf814,0xd008 @ ldrb sp, [r4, r8]") + TEST_UNSUPPORTED(".short 0xf894,0xd000 @ ldrb sp, [r4]") + + TEST_UNSUPPORTED(".short 0xf860,0x0000") /* Unallocated space */ + TEST_UNSUPPORTED(".short 0xf9ff,0xffff") /* Unallocated space */ + TEST_UNSUPPORTED(".short 0xf950,0x0000") /* Unallocated space */ + TEST_UNSUPPORTED(".short 0xf95f,0xffff") /* Unallocated space */ + TEST_UNSUPPORTED(".short 0xf800,0x0800") /* Unallocated space */ + TEST_UNSUPPORTED(".short 0xf97f,0xfaff") /* Unallocated space */ + + TEST( "pli [pc, #4]") + TEST( "pli [pc, #-4]") + TEST( "pld [pc, #4]") + TEST( "pld [pc, #-4]") + + TEST_P( "pld [r",0,-1024,", #1024]") + TEST( ".short 0xf8b0,0xf400 @ pldw [r0, #1024]") + TEST_P( "pli [r",4, 0b,", #1024]") + TEST_P( "pld [r",7, 120,", #-120]") + TEST( ".short 0xf837,0xfc78 @ pldw [r7, #-120]") + TEST_P( "pli [r",11,120,", #-120]") + TEST( "pld [sp, #0]") + + TEST_PR("pld [r",7, 24, ", r",0, 16,"]") + TEST_PR("pld [r",8, 24, ", r",12,16,", lsl #3]") + TEST_SUPPORTED(".short 0xf837,0xf000 @ pldw [r7, r0]") + TEST_SUPPORTED(".short 0xf838,0xf03c @ pldw [r8, r12, lsl #3]"); + TEST_RR("pli [r",12,0b,", r",0, 16,"]") + TEST_RR("pli [r",0, 0b,", r",12,16,", lsl #3]") + TEST_R( "pld [sp, r",1, 16,"]") + TEST_UNSUPPORTED(".short 0xf817,0xf00d @pld [r7, sp]") + TEST_UNSUPPORTED(".short 0xf817,0xf00f @pld [r7, pc]") + + TEST_GROUP("Data-processing (register)") + +#define SHIFTS32(op) \ + TEST_RR(op" r0, r",1, VAL1,", r",2, 3, "") \ + TEST_RR(op" r14, r",12,VAL2,", r",11,10,"") + + SHIFTS32("lsl") + SHIFTS32("lsls") + SHIFTS32("lsr") + SHIFTS32("lsrs") + SHIFTS32("asr") + SHIFTS32("asrs") + SHIFTS32("ror") + SHIFTS32("rors") + + TEST_UNSUPPORTED(".short 0xfa01,0xff02 @ lsl pc, r1, r2") + TEST_UNSUPPORTED(".short 0xfa01,0xfd02 @ lsl sp, r1, r2") + TEST_UNSUPPORTED(".short 0xfa0f,0xf002 @ lsl r0, pc, r2") + TEST_UNSUPPORTED(".short 0xfa0d,0xf002 @ lsl r0, sp, r2") + TEST_UNSUPPORTED(".short 0xfa01,0xf00f @ lsl r0, r1, pc") + TEST_UNSUPPORTED(".short 0xfa01,0xf00d @ lsl r0, r1, sp") + + TEST_RR( "sxtah r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "sxtah r14,r",12, HH2,", r",10,HH1,", ror #8") + TEST_R( "sxth r8, r",7, HH1,"") + + TEST_UNSUPPORTED(".short 0xfa0f,0xff87 @ sxth pc, r7"); + TEST_UNSUPPORTED(".short 0xfa0f,0xfd87 @ sxth sp, r7"); + TEST_UNSUPPORTED(".short 0xfa0f,0xf88f @ sxth r8, pc"); + TEST_UNSUPPORTED(".short 0xfa0f,0xf88d @ sxth r8, sp"); + + TEST_RR( "uxtah r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "uxtah r14,r",12, HH2,", r",10,HH1,", ror #8") + TEST_R( "uxth r8, r",7, HH1,"") + + TEST_RR( "sxtab16 r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "sxtab16 r14,r",12, HH2,", r",10,HH1,", ror #8") + TEST_R( "sxtb16 r8, r",7, HH1,"") + + TEST_RR( "uxtab16 r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "uxtab16 r14,r",12, HH2,", r",10,HH1,", ror #8") + TEST_R( "uxtb16 r8, r",7, HH1,"") + + TEST_RR( "sxtab r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "sxtab r14,r",12, HH2,", r",10,HH1,", ror #8") + TEST_R( "sxtb r8, r",7, HH1,"") + + TEST_RR( "uxtab r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "uxtab r14,r",12, HH2,", r",10,HH1,", ror #8") + TEST_R( "uxtb r8, r",7, HH1,"") + + TEST_UNSUPPORTED(".short 0xfa60,0x00f0") + TEST_UNSUPPORTED(".short 0xfa7f,0xffff") + +#define PARALLEL_ADD_SUB(op) \ + TEST_RR( op"add16 r0, r",0, HH1,", r",1, HH2,"") \ + TEST_RR( op"add16 r14, r",12,HH2,", r",10,HH1,"") \ + TEST_RR( op"asx r0, r",0, HH1,", r",1, HH2,"") \ + TEST_RR( op"asx r14, r",12,HH2,", r",10,HH1,"") \ + TEST_RR( op"sax r0, r",0, HH1,", r",1, HH2,"") \ + TEST_RR( op"sax r14, r",12,HH2,", r",10,HH1,"") \ + TEST_RR( op"sub16 r0, r",0, HH1,", r",1, HH2,"") \ + TEST_RR( op"sub16 r14, r",12,HH2,", r",10,HH1,"") \ + TEST_RR( op"add8 r0, r",0, HH1,", r",1, HH2,"") \ + TEST_RR( op"add8 r14, r",12,HH2,", r",10,HH1,"") \ + TEST_RR( op"sub8 r0, r",0, HH1,", r",1, HH2,"") \ + TEST_RR( op"sub8 r14, r",12,HH2,", r",10,HH1,"") + + TEST_GROUP("Parallel addition and subtraction, signed") + + PARALLEL_ADD_SUB("s") + PARALLEL_ADD_SUB("q") + PARALLEL_ADD_SUB("sh") + + TEST_GROUP("Parallel addition and subtraction, unsigned") + + PARALLEL_ADD_SUB("u") + PARALLEL_ADD_SUB("uq") + PARALLEL_ADD_SUB("uh") + + TEST_GROUP("Miscellaneous operations") + + TEST_RR("qadd r0, r",1, VAL1,", r",2, VAL2,"") + TEST_RR("qadd lr, r",9, VAL2,", r",8, VAL1,"") + TEST_RR("qsub r0, r",1, VAL1,", r",2, VAL2,"") + TEST_RR("qsub lr, r",9, VAL2,", r",8, VAL1,"") + TEST_RR("qdadd r0, r",1, VAL1,", r",2, VAL2,"") + TEST_RR("qdadd lr, r",9, VAL2,", r",8, VAL1,"") + TEST_RR("qdsub r0, r",1, VAL1,", r",2, VAL2,"") + TEST_RR("qdsub lr, r",9, VAL2,", r",8, VAL1,"") + + TEST_R("rev.w r0, r",0, VAL1,"") + TEST_R("rev r14, r",12, VAL2,"") + TEST_R("rev16.w r0, r",0, VAL1,"") + TEST_R("rev16 r14, r",12, VAL2,"") + TEST_R("rbit r0, r",0, VAL1,"") + TEST_R("rbit r14, r",12, VAL2,"") + TEST_R("revsh.w r0, r",0, VAL1,"") + TEST_R("revsh r14, r",12, VAL2,"") + + TEST_UNSUPPORTED(".short 0xfa9c,0xff8c @ rev pc, r12"); + TEST_UNSUPPORTED(".short 0xfa9c,0xfd8c @ rev sp, r12"); + TEST_UNSUPPORTED(".short 0xfa9f,0xfe8f @ rev r14, pc"); + TEST_UNSUPPORTED(".short 0xfa9d,0xfe8d @ rev r14, sp"); + + TEST_RR("sel r0, r",0, VAL1,", r",1, VAL2,"") + TEST_RR("sel r14, r",12,VAL1,", r",10, VAL2,"") + + TEST_R("clz r0, r",0, 0x0,"") + TEST_R("clz r7, r",14,0x1,"") + TEST_R("clz lr, r",7, 0xffffffff,"") + + TEST_UNSUPPORTED(".short 0xfa80,0xf030") /* Unallocated space */ + TEST_UNSUPPORTED(".short 0xfaff,0xff7f") /* Unallocated space */ + TEST_UNSUPPORTED(".short 0xfab0,0xf000") /* Unallocated space */ + TEST_UNSUPPORTED(".short 0xfaff,0xff7f") /* Unallocated space */ + + TEST_GROUP("Multiply, multiply accumulate, and absolute difference operations") + + TEST_RR( "mul r0, r",1, VAL1,", r",2, VAL2,"") + TEST_RR( "mul r7, r",8, VAL2,", r",9, VAL2,"") + TEST_UNSUPPORTED(".short 0xfb08,0xff09 @ mul pc, r8, r9") + TEST_UNSUPPORTED(".short 0xfb08,0xfd09 @ mul sp, r8, r9") + TEST_UNSUPPORTED(".short 0xfb0f,0xf709 @ mul r7, pc, r9") + TEST_UNSUPPORTED(".short 0xfb0d,0xf709 @ mul r7, sp, r9") + TEST_UNSUPPORTED(".short 0xfb08,0xf70f @ mul r7, r8, pc") + TEST_UNSUPPORTED(".short 0xfb08,0xf70d @ mul r7, r8, sp") + + TEST_RRR( "mla r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") + TEST_RRR( "mla r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") + TEST_UNSUPPORTED(".short 0xfb08,0xaf09 @ mla pc, r8, r9, r10"); + TEST_UNSUPPORTED(".short 0xfb08,0xad09 @ mla sp, r8, r9, r10"); + TEST_UNSUPPORTED(".short 0xfb0f,0xa709 @ mla r7, pc, r9, r10"); + TEST_UNSUPPORTED(".short 0xfb0d,0xa709 @ mla r7, sp, r9, r10"); + TEST_UNSUPPORTED(".short 0xfb08,0xa70f @ mla r7, r8, pc, r10"); + TEST_UNSUPPORTED(".short 0xfb08,0xa70d @ mla r7, r8, sp, r10"); + TEST_UNSUPPORTED(".short 0xfb08,0xd709 @ mla r7, r8, r9, sp"); + + TEST_RRR( "mls r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") + TEST_RRR( "mls r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") + + TEST_RRR( "smlabb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") + TEST_RRR( "smlabb r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") + TEST_RRR( "smlatb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") + TEST_RRR( "smlatb r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") + TEST_RRR( "smlabt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") + TEST_RRR( "smlabt r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") + TEST_RRR( "smlatt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") + TEST_RRR( "smlatt r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") + TEST_RR( "smulbb r0, r",1, VAL1,", r",2, VAL2,"") + TEST_RR( "smulbb r7, r",8, VAL3,", r",9, VAL1,"") + TEST_RR( "smultb r0, r",1, VAL1,", r",2, VAL2,"") + TEST_RR( "smultb r7, r",8, VAL3,", r",9, VAL1,"") + TEST_RR( "smulbt r0, r",1, VAL1,", r",2, VAL2,"") + TEST_RR( "smulbt r7, r",8, VAL3,", r",9, VAL1,"") + TEST_RR( "smultt r0, r",1, VAL1,", r",2, VAL2,"") + TEST_RR( "smultt r7, r",8, VAL3,", r",9, VAL1,"") + + TEST_RRR( "smlad r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"") + TEST_RRR( "smlad r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"") + TEST_RRR( "smladx r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"") + TEST_RRR( "smladx r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"") + TEST_RR( "smuad r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "smuad r14, r",12,HH2,", r",10,HH1,"") + TEST_RR( "smuadx r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "smuadx r14, r",12,HH2,", r",10,HH1,"") + + TEST_RRR( "smlawb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") + TEST_RRR( "smlawb r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") + TEST_RRR( "smlawt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") + TEST_RRR( "smlawt r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") + TEST_RR( "smulwb r0, r",1, VAL1,", r",2, VAL2,"") + TEST_RR( "smulwb r7, r",8, VAL3,", r",9, VAL1,"") + TEST_RR( "smulwt r0, r",1, VAL1,", r",2, VAL2,"") + TEST_RR( "smulwt r7, r",8, VAL3,", r",9, VAL1,"") + + TEST_RRR( "smlsd r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"") + TEST_RRR( "smlsd r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"") + TEST_RRR( "smlsdx r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"") + TEST_RRR( "smlsdx r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"") + TEST_RR( "smusd r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "smusd r14, r",12,HH2,", r",10,HH1,"") + TEST_RR( "smusdx r0, r",0, HH1,", r",1, HH2,"") + TEST_RR( "smusdx r14, r",12,HH2,", r",10,HH1,"") + + TEST_RRR( "smmla r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"") + TEST_RRR( "smmla r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"") + TEST_RRR( "smmlar r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"") + TEST_RRR( "smmlar r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"") + TEST_RR( "smmul r0, r",0, VAL1,", r",1, VAL2,"") + TEST_RR( "smmul r14, r",12,VAL2,", r",10,VAL1,"") + TEST_RR( "smmulr r0, r",0, VAL1,", r",1, VAL2,"") + TEST_RR( "smmulr r14, r",12,VAL2,", r",10,VAL1,"") + + TEST_RRR( "smmls r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"") + TEST_RRR( "smmls r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"") + TEST_RRR( "smmlsr r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"") + TEST_RRR( "smmlsr r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"") + + TEST_RRR( "usada8 r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL3,"") + TEST_RRR( "usada8 r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL3,"") + TEST_RR( "usad8 r0, r",0, VAL1,", r",1, VAL2,"") + TEST_RR( "usad8 r14, r",12,VAL2,", r",10,VAL1,"") + + TEST_UNSUPPORTED(".short 0xfb00,0xf010") /* Unallocated space */ + TEST_UNSUPPORTED(".short 0xfb0f,0xff1f") /* Unallocated space */ + TEST_UNSUPPORTED(".short 0xfb70,0xf010") /* Unallocated space */ + TEST_UNSUPPORTED(".short 0xfb7f,0xff1f") /* Unallocated space */ + TEST_UNSUPPORTED(".short 0xfb70,0x0010") /* Unallocated space */ + TEST_UNSUPPORTED(".short 0xfb7f,0xff1f") /* Unallocated space */ + + TEST_GROUP("Long multiply, long multiply accumulate, and divide") + + TEST_RR( "smull r0, r1, r",2, VAL1,", r",3, VAL2,"") + TEST_RR( "smull r7, r8, r",9, VAL2,", r",10, VAL1,"") + TEST_UNSUPPORTED(".short 0xfb89,0xf80a @ smull pc, r8, r9, r10"); + TEST_UNSUPPORTED(".short 0xfb89,0xd80a @ smull sp, r8, r9, r10"); + TEST_UNSUPPORTED(".short 0xfb89,0x7f0a @ smull r7, pc, r9, r10"); + TEST_UNSUPPORTED(".short 0xfb89,0x7d0a @ smull r7, sp, r9, r10"); + TEST_UNSUPPORTED(".short 0xfb8f,0x780a @ smull r7, r8, pc, r10"); + TEST_UNSUPPORTED(".short 0xfb8d,0x780a @ smull r7, r8, sp, r10"); + TEST_UNSUPPORTED(".short 0xfb89,0x780f @ smull r7, r8, r9, pc"); + TEST_UNSUPPORTED(".short 0xfb89,0x780d @ smull r7, r8, r9, sp"); + + TEST_RR( "umull r0, r1, r",2, VAL1,", r",3, VAL2,"") + TEST_RR( "umull r7, r8, r",9, VAL2,", r",10, VAL1,"") + + TEST_RRRR( "smlal r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) + TEST_RRRR( "smlal r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) + + TEST_RRRR( "smlalbb r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) + TEST_RRRR( "smlalbb r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) + TEST_RRRR( "smlalbt r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) + TEST_RRRR( "smlalbt r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) + TEST_RRRR( "smlaltb r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) + TEST_RRRR( "smlaltb r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) + TEST_RRRR( "smlaltt r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) + TEST_RRRR( "smlaltt r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) + + TEST_RRRR( "smlald r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2) + TEST_RRRR( "smlald r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1) + TEST_RRRR( "smlaldx r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2) + TEST_RRRR( "smlaldx r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1) + + TEST_RRRR( "smlsld r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2) + TEST_RRRR( "smlsld r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1) + TEST_RRRR( "smlsldx r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2) + TEST_RRRR( "smlsldx r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1) + + TEST_RRRR( "umlal r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) + TEST_RRRR( "umlal r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) + TEST_RRRR( "umaal r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) + TEST_RRRR( "umaal r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) + + TEST_GROUP("Coprocessor instructions") + + TEST_UNSUPPORTED(".short 0xfc00,0x0000") + TEST_UNSUPPORTED(".short 0xffff,0xffff") + + TEST_GROUP("Testing instructions in IT blocks") + + TEST_ITBLOCK("sub.w r0, r0") + + verbose("\n"); +} + diff --git a/arch/arm/kernel/kprobes-test.c b/arch/arm/kernel/kprobes-test.c new file mode 100644 index 0000000000000000000000000000000000000000..e17cdd6d90d8734553835e5b49bd87027226c1ad --- /dev/null +++ b/arch/arm/kernel/kprobes-test.c @@ -0,0 +1,1748 @@ +/* + * arch/arm/kernel/kprobes-test.c + * + * Copyright (C) 2011 Jon Medhurst . + * + * 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 file contains test code for ARM kprobes. + * + * The top level function run_all_tests() executes tests for all of the + * supported instruction sets: ARM, 16-bit Thumb, and 32-bit Thumb. These tests + * fall into two categories; run_api_tests() checks basic functionality of the + * kprobes API, and run_test_cases() is a comprehensive test for kprobes + * instruction decoding and simulation. + * + * run_test_cases() first checks the kprobes decoding table for self consistency + * (using table_test()) then executes a series of test cases for each of the CPU + * instruction forms. coverage_start() and coverage_end() are used to verify + * that these test cases cover all of the possible combinations of instructions + * described by the kprobes decoding tables. + * + * The individual test cases are in kprobes-test-arm.c and kprobes-test-thumb.c + * which use the macros defined in kprobes-test.h. The rest of this + * documentation will describe the operation of the framework used by these + * test cases. + */ + +/* + * TESTING METHODOLOGY + * ------------------- + * + * The methodology used to test an ARM instruction 'test_insn' is to use + * inline assembler like: + * + * test_before: nop + * test_case: test_insn + * test_after: nop + * + * When the test case is run a kprobe is placed of each nop. The + * post-handler of the test_before probe is used to modify the saved CPU + * register context to that which we require for the test case. The + * pre-handler of the of the test_after probe saves a copy of the CPU + * register context. In this way we can execute test_insn with a specific + * register context and see the results afterwards. + * + * To actually test the kprobes instruction emulation we perform the above + * step a second time but with an additional kprobe on the test_case + * instruction itself. If the emulation is accurate then the results seen + * by the test_after probe will be identical to the first run which didn't + * have a probe on test_case. + * + * Each test case is run several times with a variety of variations in the + * flags value of stored in CPSR, and for Thumb code, different ITState. + * + * For instructions which can modify PC, a second test_after probe is used + * like this: + * + * test_before: nop + * test_case: test_insn + * test_after: nop + * b test_done + * test_after2: nop + * test_done: + * + * The test case is constructed such that test_insn branches to + * test_after2, or, if testing a conditional instruction, it may just + * continue to test_after. The probes inserted at both locations let us + * determine which happened. A similar approach is used for testing + * backwards branches... + * + * b test_before + * b test_done @ helps to cope with off by 1 branches + * test_after2: nop + * b test_done + * test_before: nop + * test_case: test_insn + * test_after: nop + * test_done: + * + * The macros used to generate the assembler instructions describe above + * are TEST_INSTRUCTION, TEST_BRANCH_F (branch forwards) and TEST_BRANCH_B + * (branch backwards). In these, the local variables numbered 1, 50, 2 and + * 99 represent: test_before, test_case, test_after2 and test_done. + * + * FRAMEWORK + * --------- + * + * Each test case is wrapped between the pair of macros TESTCASE_START and + * TESTCASE_END. As well as performing the inline assembler boilerplate, + * these call out to the kprobes_test_case_start() and + * kprobes_test_case_end() functions which drive the execution of the test + * case. The specific arguments to use for each test case are stored as + * inline data constructed using the various TEST_ARG_* macros. Putting + * this all together, a simple test case may look like: + * + * TESTCASE_START("Testing mov r0, r7") + * TEST_ARG_REG(7, 0x12345678) // Set r7=0x12345678 + * TEST_ARG_END("") + * TEST_INSTRUCTION("mov r0, r7") + * TESTCASE_END + * + * Note, in practice the single convenience macro TEST_R would be used for this + * instead. + * + * The above would expand to assembler looking something like: + * + * @ TESTCASE_START + * bl __kprobes_test_case_start + * @ start of inline data... + * .ascii "mov r0, r7" @ text title for test case + * .byte 0 + * .align 2 + * + * @ TEST_ARG_REG + * .byte ARG_TYPE_REG + * .byte 7 + * .short 0 + * .word 0x1234567 + * + * @ TEST_ARG_END + * .byte ARG_TYPE_END + * .byte TEST_ISA @ flags, including ISA being tested + * .short 50f-0f @ offset of 'test_before' + * .short 2f-0f @ offset of 'test_after2' (if relevent) + * .short 99f-0f @ offset of 'test_done' + * @ start of test case code... + * 0: + * .code TEST_ISA @ switch to ISA being tested + * + * @ TEST_INSTRUCTION + * 50: nop @ location for 'test_before' probe + * 1: mov r0, r7 @ the test case instruction 'test_insn' + * nop @ location for 'test_after' probe + * + * // TESTCASE_END + * 2: + * 99: bl __kprobes_test_case_end_##TEST_ISA + * .code NONMAL_ISA + * + * When the above is execute the following happens... + * + * __kprobes_test_case_start() is an assembler wrapper which sets up space + * for a stack buffer and calls the C function kprobes_test_case_start(). + * This C function will do some initial processing of the inline data and + * setup some global state. It then inserts the test_before and test_after + * kprobes and returns a value which causes the assembler wrapper to jump + * to the start of the test case code, (local label '0'). + * + * When the test case code executes, the test_before probe will be hit and + * test_before_post_handler will call setup_test_context(). This fills the + * stack buffer and CPU registers with a test pattern and then processes + * the test case arguments. In our example there is one TEST_ARG_REG which + * indicates that R7 should be loaded with the value 0x12345678. + * + * When the test_before probe ends, the test case continues and executes + * the "mov r0, r7" instruction. It then hits the test_after probe and the + * pre-handler for this (test_after_pre_handler) will save a copy of the + * CPU register context. This should now have R0 holding the same value as + * R7. + * + * Finally we get to the call to __kprobes_test_case_end_{32,16}. This is + * an assembler wrapper which switches back to the ISA used by the test + * code and calls the C function kprobes_test_case_end(). + * + * For each run through the test case, test_case_run_count is incremented + * by one. For even runs, kprobes_test_case_end() saves a copy of the + * register and stack buffer contents from the test case just run. It then + * inserts a kprobe on the test case instruction 'test_insn' and returns a + * value to cause the test case code to be re-run. + * + * For odd numbered runs, kprobes_test_case_end() compares the register and + * stack buffer contents to those that were saved on the previous even + * numbered run (the one without the kprobe on test_insn). These should be + * the same if the kprobe instruction simulation routine is correct. + * + * The pair of test case runs is repeated with different combinations of + * flag values in CPSR and, for Thumb, different ITState. This is + * controlled by test_context_cpsr(). + * + * BUILDING TEST CASES + * ------------------- + * + * + * As an aid to building test cases, the stack buffer is initialised with + * some special values: + * + * [SP+13*4] Contains SP+120. This can be used to test instructions + * which load a value into SP. + * + * [SP+15*4] When testing branching instructions using TEST_BRANCH_{F,B}, + * this holds the target address of the branch, 'test_after2'. + * This can be used to test instructions which load a PC value + * from memory. + */ + +#include +#include +#include +#include + +#include "kprobes.h" +#include "kprobes-test.h" + + +#define BENCHMARKING 1 + + +/* + * Test basic API + */ + +static bool test_regs_ok; +static int test_func_instance; +static int pre_handler_called; +static int post_handler_called; +static int jprobe_func_called; +static int kretprobe_handler_called; + +#define FUNC_ARG1 0x12345678 +#define FUNC_ARG2 0xabcdef + + +#ifndef CONFIG_THUMB2_KERNEL + +long arm_func(long r0, long r1); + +static void __used __naked __arm_kprobes_test_func(void) +{ + __asm__ __volatile__ ( + ".arm \n\t" + ".type arm_func, %%function \n\t" + "arm_func: \n\t" + "adds r0, r0, r1 \n\t" + "bx lr \n\t" + ".code "NORMAL_ISA /* Back to Thumb if necessary */ + : : : "r0", "r1", "cc" + ); +} + +#else /* CONFIG_THUMB2_KERNEL */ + +long thumb16_func(long r0, long r1); +long thumb32even_func(long r0, long r1); +long thumb32odd_func(long r0, long r1); + +static void __used __naked __thumb_kprobes_test_funcs(void) +{ + __asm__ __volatile__ ( + ".type thumb16_func, %%function \n\t" + "thumb16_func: \n\t" + "adds.n r0, r0, r1 \n\t" + "bx lr \n\t" + + ".align \n\t" + ".type thumb32even_func, %%function \n\t" + "thumb32even_func: \n\t" + "adds.w r0, r0, r1 \n\t" + "bx lr \n\t" + + ".align \n\t" + "nop.n \n\t" + ".type thumb32odd_func, %%function \n\t" + "thumb32odd_func: \n\t" + "adds.w r0, r0, r1 \n\t" + "bx lr \n\t" + + : : : "r0", "r1", "cc" + ); +} + +#endif /* CONFIG_THUMB2_KERNEL */ + + +static int call_test_func(long (*func)(long, long), bool check_test_regs) +{ + long ret; + + ++test_func_instance; + test_regs_ok = false; + + ret = (*func)(FUNC_ARG1, FUNC_ARG2); + if (ret != FUNC_ARG1 + FUNC_ARG2) { + pr_err("FAIL: call_test_func: func returned %lx\n", ret); + return false; + } + + if (check_test_regs && !test_regs_ok) { + pr_err("FAIL: test regs not OK\n"); + return false; + } + + return true; +} + +static int __kprobes pre_handler(struct kprobe *p, struct pt_regs *regs) +{ + pre_handler_called = test_func_instance; + if (regs->ARM_r0 == FUNC_ARG1 && regs->ARM_r1 == FUNC_ARG2) + test_regs_ok = true; + return 0; +} + +static void __kprobes post_handler(struct kprobe *p, struct pt_regs *regs, + unsigned long flags) +{ + post_handler_called = test_func_instance; + if (regs->ARM_r0 != FUNC_ARG1 + FUNC_ARG2 || regs->ARM_r1 != FUNC_ARG2) + test_regs_ok = false; +} + +static struct kprobe the_kprobe = { + .addr = 0, + .pre_handler = pre_handler, + .post_handler = post_handler +}; + +static int test_kprobe(long (*func)(long, long)) +{ + int ret; + + the_kprobe.addr = (kprobe_opcode_t *)func; + ret = register_kprobe(&the_kprobe); + if (ret < 0) { + pr_err("FAIL: register_kprobe failed with %d\n", ret); + return ret; + } + + ret = call_test_func(func, true); + + unregister_kprobe(&the_kprobe); + the_kprobe.flags = 0; /* Clear disable flag to allow reuse */ + + if (!ret) + return -EINVAL; + if (pre_handler_called != test_func_instance) { + pr_err("FAIL: kprobe pre_handler not called\n"); + return -EINVAL; + } + if (post_handler_called != test_func_instance) { + pr_err("FAIL: kprobe post_handler not called\n"); + return -EINVAL; + } + if (!call_test_func(func, false)) + return -EINVAL; + if (pre_handler_called == test_func_instance || + post_handler_called == test_func_instance) { + pr_err("FAIL: probe called after unregistering\n"); + return -EINVAL; + } + + return 0; +} + +static void __kprobes jprobe_func(long r0, long r1) +{ + jprobe_func_called = test_func_instance; + if (r0 == FUNC_ARG1 && r1 == FUNC_ARG2) + test_regs_ok = true; + jprobe_return(); +} + +static struct jprobe the_jprobe = { + .entry = jprobe_func, +}; + +static int test_jprobe(long (*func)(long, long)) +{ + int ret; + + the_jprobe.kp.addr = (kprobe_opcode_t *)func; + ret = register_jprobe(&the_jprobe); + if (ret < 0) { + pr_err("FAIL: register_jprobe failed with %d\n", ret); + return ret; + } + + ret = call_test_func(func, true); + + unregister_jprobe(&the_jprobe); + the_jprobe.kp.flags = 0; /* Clear disable flag to allow reuse */ + + if (!ret) + return -EINVAL; + if (jprobe_func_called != test_func_instance) { + pr_err("FAIL: jprobe handler function not called\n"); + return -EINVAL; + } + if (!call_test_func(func, false)) + return -EINVAL; + if (jprobe_func_called == test_func_instance) { + pr_err("FAIL: probe called after unregistering\n"); + return -EINVAL; + } + + return 0; +} + +static int __kprobes +kretprobe_handler(struct kretprobe_instance *ri, struct pt_regs *regs) +{ + kretprobe_handler_called = test_func_instance; + if (regs_return_value(regs) == FUNC_ARG1 + FUNC_ARG2) + test_regs_ok = true; + return 0; +} + +static struct kretprobe the_kretprobe = { + .handler = kretprobe_handler, +}; + +static int test_kretprobe(long (*func)(long, long)) +{ + int ret; + + the_kretprobe.kp.addr = (kprobe_opcode_t *)func; + ret = register_kretprobe(&the_kretprobe); + if (ret < 0) { + pr_err("FAIL: register_kretprobe failed with %d\n", ret); + return ret; + } + + ret = call_test_func(func, true); + + unregister_kretprobe(&the_kretprobe); + the_kretprobe.kp.flags = 0; /* Clear disable flag to allow reuse */ + + if (!ret) + return -EINVAL; + if (kretprobe_handler_called != test_func_instance) { + pr_err("FAIL: kretprobe handler not called\n"); + return -EINVAL; + } + if (!call_test_func(func, false)) + return -EINVAL; + if (jprobe_func_called == test_func_instance) { + pr_err("FAIL: kretprobe called after unregistering\n"); + return -EINVAL; + } + + return 0; +} + +static int run_api_tests(long (*func)(long, long)) +{ + int ret; + + pr_info(" kprobe\n"); + ret = test_kprobe(func); + if (ret < 0) + return ret; + + pr_info(" jprobe\n"); + ret = test_jprobe(func); + if (ret < 0) + return ret; + + pr_info(" kretprobe\n"); + ret = test_kretprobe(func); + if (ret < 0) + return ret; + + return 0; +} + + +/* + * Benchmarking + */ + +#if BENCHMARKING + +static void __naked benchmark_nop(void) +{ + __asm__ __volatile__ ( + "nop \n\t" + "bx lr" + ); +} + +#ifdef CONFIG_THUMB2_KERNEL +#define wide ".w" +#else +#define wide +#endif + +static void __naked benchmark_pushpop1(void) +{ + __asm__ __volatile__ ( + "stmdb"wide" sp!, {r3-r11,lr} \n\t" + "ldmia"wide" sp!, {r3-r11,pc}" + ); +} + +static void __naked benchmark_pushpop2(void) +{ + __asm__ __volatile__ ( + "stmdb"wide" sp!, {r0-r8,lr} \n\t" + "ldmia"wide" sp!, {r0-r8,pc}" + ); +} + +static void __naked benchmark_pushpop3(void) +{ + __asm__ __volatile__ ( + "stmdb"wide" sp!, {r4,lr} \n\t" + "ldmia"wide" sp!, {r4,pc}" + ); +} + +static void __naked benchmark_pushpop4(void) +{ + __asm__ __volatile__ ( + "stmdb"wide" sp!, {r0,lr} \n\t" + "ldmia"wide" sp!, {r0,pc}" + ); +} + + +#ifdef CONFIG_THUMB2_KERNEL + +static void __naked benchmark_pushpop_thumb(void) +{ + __asm__ __volatile__ ( + "push.n {r0-r7,lr} \n\t" + "pop.n {r0-r7,pc}" + ); +} + +#endif + +static int __kprobes +benchmark_pre_handler(struct kprobe *p, struct pt_regs *regs) +{ + return 0; +} + +static int benchmark(void(*fn)(void)) +{ + unsigned n, i, t, t0; + + for (n = 1000; ; n *= 2) { + t0 = sched_clock(); + for (i = n; i > 0; --i) + fn(); + t = sched_clock() - t0; + if (t >= 250000000) + break; /* Stop once we took more than 0.25 seconds */ + } + return t / n; /* Time for one iteration in nanoseconds */ +}; + +static int kprobe_benchmark(void(*fn)(void), unsigned offset) +{ + struct kprobe k = { + .addr = (kprobe_opcode_t *)((uintptr_t)fn + offset), + .pre_handler = benchmark_pre_handler, + }; + + int ret = register_kprobe(&k); + if (ret < 0) { + pr_err("FAIL: register_kprobe failed with %d\n", ret); + return ret; + } + + ret = benchmark(fn); + + unregister_kprobe(&k); + return ret; +}; + +struct benchmarks { + void (*fn)(void); + unsigned offset; + const char *title; +}; + +static int run_benchmarks(void) +{ + int ret; + struct benchmarks list[] = { + {&benchmark_nop, 0, "nop"}, + /* + * benchmark_pushpop{1,3} will have the optimised + * instruction emulation, whilst benchmark_pushpop{2,4} will + * be the equivalent unoptimised instructions. + */ + {&benchmark_pushpop1, 0, "stmdb sp!, {r3-r11,lr}"}, + {&benchmark_pushpop1, 4, "ldmia sp!, {r3-r11,pc}"}, + {&benchmark_pushpop2, 0, "stmdb sp!, {r0-r8,lr}"}, + {&benchmark_pushpop2, 4, "ldmia sp!, {r0-r8,pc}"}, + {&benchmark_pushpop3, 0, "stmdb sp!, {r4,lr}"}, + {&benchmark_pushpop3, 4, "ldmia sp!, {r4,pc}"}, + {&benchmark_pushpop4, 0, "stmdb sp!, {r0,lr}"}, + {&benchmark_pushpop4, 4, "ldmia sp!, {r0,pc}"}, +#ifdef CONFIG_THUMB2_KERNEL + {&benchmark_pushpop_thumb, 0, "push.n {r0-r7,lr}"}, + {&benchmark_pushpop_thumb, 2, "pop.n {r0-r7,pc}"}, +#endif + {0} + }; + + struct benchmarks *b; + for (b = list; b->fn; ++b) { + ret = kprobe_benchmark(b->fn, b->offset); + if (ret < 0) + return ret; + pr_info(" %dns for kprobe %s\n", ret, b->title); + } + + pr_info("\n"); + return 0; +} + +#endif /* BENCHMARKING */ + + +/* + * Decoding table self-consistency tests + */ + +static const int decode_struct_sizes[NUM_DECODE_TYPES] = { + [DECODE_TYPE_TABLE] = sizeof(struct decode_table), + [DECODE_TYPE_CUSTOM] = sizeof(struct decode_custom), + [DECODE_TYPE_SIMULATE] = sizeof(struct decode_simulate), + [DECODE_TYPE_EMULATE] = sizeof(struct decode_emulate), + [DECODE_TYPE_OR] = sizeof(struct decode_or), + [DECODE_TYPE_REJECT] = sizeof(struct decode_reject) +}; + +static int table_iter(const union decode_item *table, + int (*fn)(const struct decode_header *, void *), + void *args) +{ + const struct decode_header *h = (struct decode_header *)table; + int result; + + for (;;) { + enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK; + + if (type == DECODE_TYPE_END) + return 0; + + result = fn(h, args); + if (result) + return result; + + h = (struct decode_header *) + ((uintptr_t)h + decode_struct_sizes[type]); + + } +} + +static int table_test_fail(const struct decode_header *h, const char* message) +{ + + pr_err("FAIL: kprobes test failure \"%s\" (mask %08x, value %08x)\n", + message, h->mask.bits, h->value.bits); + return -EINVAL; +} + +struct table_test_args { + const union decode_item *root_table; + u32 parent_mask; + u32 parent_value; +}; + +static int table_test_fn(const struct decode_header *h, void *args) +{ + struct table_test_args *a = (struct table_test_args *)args; + enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK; + + if (h->value.bits & ~h->mask.bits) + return table_test_fail(h, "Match value has bits not in mask"); + + if ((h->mask.bits & a->parent_mask) != a->parent_mask) + return table_test_fail(h, "Mask has bits not in parent mask"); + + if ((h->value.bits ^ a->parent_value) & a->parent_mask) + return table_test_fail(h, "Value is inconsistent with parent"); + + if (type == DECODE_TYPE_TABLE) { + struct decode_table *d = (struct decode_table *)h; + struct table_test_args args2 = *a; + args2.parent_mask = h->mask.bits; + args2.parent_value = h->value.bits; + return table_iter(d->table.table, table_test_fn, &args2); + } + + return 0; +} + +static int table_test(const union decode_item *table) +{ + struct table_test_args args = { + .root_table = table, + .parent_mask = 0, + .parent_value = 0 + }; + return table_iter(args.root_table, table_test_fn, &args); +} + + +/* + * Decoding table test coverage analysis + * + * coverage_start() builds a coverage_table which contains a list of + * coverage_entry's to match each entry in the specified kprobes instruction + * decoding table. + * + * When test cases are run, coverage_add() is called to process each case. + * This looks up the corresponding entry in the coverage_table and sets it as + * being matched, as well as clearing the regs flag appropriate for the test. + * + * After all test cases have been run, coverage_end() is called to check that + * all entries in coverage_table have been matched and that all regs flags are + * cleared. I.e. that all possible combinations of instructions described by + * the kprobes decoding tables have had a test case executed for them. + */ + +bool coverage_fail; + +#define MAX_COVERAGE_ENTRIES 256 + +struct coverage_entry { + const struct decode_header *header; + unsigned regs; + unsigned nesting; + char matched; +}; + +struct coverage_table { + struct coverage_entry *base; + unsigned num_entries; + unsigned nesting; +}; + +struct coverage_table coverage; + +#define COVERAGE_ANY_REG (1<<0) +#define COVERAGE_SP (1<<1) +#define COVERAGE_PC (1<<2) +#define COVERAGE_PCWB (1<<3) + +static const char coverage_register_lookup[16] = { + [REG_TYPE_ANY] = COVERAGE_ANY_REG | COVERAGE_SP | COVERAGE_PC, + [REG_TYPE_SAMEAS16] = COVERAGE_ANY_REG, + [REG_TYPE_SP] = COVERAGE_SP, + [REG_TYPE_PC] = COVERAGE_PC, + [REG_TYPE_NOSP] = COVERAGE_ANY_REG | COVERAGE_SP, + [REG_TYPE_NOSPPC] = COVERAGE_ANY_REG | COVERAGE_SP | COVERAGE_PC, + [REG_TYPE_NOPC] = COVERAGE_ANY_REG | COVERAGE_PC, + [REG_TYPE_NOPCWB] = COVERAGE_ANY_REG | COVERAGE_PC | COVERAGE_PCWB, + [REG_TYPE_NOPCX] = COVERAGE_ANY_REG, + [REG_TYPE_NOSPPCX] = COVERAGE_ANY_REG | COVERAGE_SP, +}; + +unsigned coverage_start_registers(const struct decode_header *h) +{ + unsigned regs = 0; + int i; + for (i = 0; i < 20; i += 4) { + int r = (h->type_regs.bits >> (DECODE_TYPE_BITS + i)) & 0xf; + regs |= coverage_register_lookup[r] << i; + } + return regs; +} + +static int coverage_start_fn(const struct decode_header *h, void *args) +{ + struct coverage_table *coverage = (struct coverage_table *)args; + enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK; + struct coverage_entry *entry = coverage->base + coverage->num_entries; + + if (coverage->num_entries == MAX_COVERAGE_ENTRIES - 1) { + pr_err("FAIL: Out of space for test coverage data"); + return -ENOMEM; + } + + ++coverage->num_entries; + + entry->header = h; + entry->regs = coverage_start_registers(h); + entry->nesting = coverage->nesting; + entry->matched = false; + + if (type == DECODE_TYPE_TABLE) { + struct decode_table *d = (struct decode_table *)h; + int ret; + ++coverage->nesting; + ret = table_iter(d->table.table, coverage_start_fn, coverage); + --coverage->nesting; + return ret; + } + + return 0; +} + +static int coverage_start(const union decode_item *table) +{ + coverage.base = kmalloc(MAX_COVERAGE_ENTRIES * + sizeof(struct coverage_entry), GFP_KERNEL); + coverage.num_entries = 0; + coverage.nesting = 0; + return table_iter(table, coverage_start_fn, &coverage); +} + +static void +coverage_add_registers(struct coverage_entry *entry, kprobe_opcode_t insn) +{ + int regs = entry->header->type_regs.bits >> DECODE_TYPE_BITS; + int i; + for (i = 0; i < 20; i += 4) { + enum decode_reg_type reg_type = (regs >> i) & 0xf; + int reg = (insn >> i) & 0xf; + int flag; + + if (!reg_type) + continue; + + if (reg == 13) + flag = COVERAGE_SP; + else if (reg == 15) + flag = COVERAGE_PC; + else + flag = COVERAGE_ANY_REG; + entry->regs &= ~(flag << i); + + switch (reg_type) { + + case REG_TYPE_NONE: + case REG_TYPE_ANY: + case REG_TYPE_SAMEAS16: + break; + + case REG_TYPE_SP: + if (reg != 13) + return; + break; + + case REG_TYPE_PC: + if (reg != 15) + return; + break; + + case REG_TYPE_NOSP: + if (reg == 13) + return; + break; + + case REG_TYPE_NOSPPC: + case REG_TYPE_NOSPPCX: + if (reg == 13 || reg == 15) + return; + break; + + case REG_TYPE_NOPCWB: + if (!is_writeback(insn)) + break; + if (reg == 15) { + entry->regs &= ~(COVERAGE_PCWB << i); + return; + } + break; + + case REG_TYPE_NOPC: + case REG_TYPE_NOPCX: + if (reg == 15) + return; + break; + } + + } +} + +static void coverage_add(kprobe_opcode_t insn) +{ + struct coverage_entry *entry = coverage.base; + struct coverage_entry *end = coverage.base + coverage.num_entries; + bool matched = false; + unsigned nesting = 0; + + for (; entry < end; ++entry) { + const struct decode_header *h = entry->header; + enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK; + + if (entry->nesting > nesting) + continue; /* Skip sub-table we didn't match */ + + if (entry->nesting < nesting) + break; /* End of sub-table we were scanning */ + + if (!matched) { + if ((insn & h->mask.bits) != h->value.bits) + continue; + entry->matched = true; + } + + switch (type) { + + case DECODE_TYPE_TABLE: + ++nesting; + break; + + case DECODE_TYPE_CUSTOM: + case DECODE_TYPE_SIMULATE: + case DECODE_TYPE_EMULATE: + coverage_add_registers(entry, insn); + return; + + case DECODE_TYPE_OR: + matched = true; + break; + + case DECODE_TYPE_REJECT: + default: + return; + } + + } +} + +static void coverage_end(void) +{ + struct coverage_entry *entry = coverage.base; + struct coverage_entry *end = coverage.base + coverage.num_entries; + + for (; entry < end; ++entry) { + u32 mask = entry->header->mask.bits; + u32 value = entry->header->value.bits; + + if (entry->regs) { + pr_err("FAIL: Register test coverage missing for %08x %08x (%05x)\n", + mask, value, entry->regs); + coverage_fail = true; + } + if (!entry->matched) { + pr_err("FAIL: Test coverage entry missing for %08x %08x\n", + mask, value); + coverage_fail = true; + } + } + + kfree(coverage.base); +} + + +/* + * Framework for instruction set test cases + */ + +void __naked __kprobes_test_case_start(void) +{ + __asm__ __volatile__ ( + "stmdb sp!, {r4-r11} \n\t" + "sub sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t" + "bic r0, lr, #1 @ r0 = inline title string \n\t" + "mov r1, sp \n\t" + "bl kprobes_test_case_start \n\t" + "bx r0 \n\t" + ); +} + +#ifndef CONFIG_THUMB2_KERNEL + +void __naked __kprobes_test_case_end_32(void) +{ + __asm__ __volatile__ ( + "mov r4, lr \n\t" + "bl kprobes_test_case_end \n\t" + "cmp r0, #0 \n\t" + "movne pc, r0 \n\t" + "mov r0, r4 \n\t" + "add sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t" + "ldmia sp!, {r4-r11} \n\t" + "mov pc, r0 \n\t" + ); +} + +#else /* CONFIG_THUMB2_KERNEL */ + +void __naked __kprobes_test_case_end_16(void) +{ + __asm__ __volatile__ ( + "mov r4, lr \n\t" + "bl kprobes_test_case_end \n\t" + "cmp r0, #0 \n\t" + "bxne r0 \n\t" + "mov r0, r4 \n\t" + "add sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t" + "ldmia sp!, {r4-r11} \n\t" + "bx r0 \n\t" + ); +} + +void __naked __kprobes_test_case_end_32(void) +{ + __asm__ __volatile__ ( + ".arm \n\t" + "orr lr, lr, #1 @ will return to Thumb code \n\t" + "ldr pc, 1f \n\t" + "1: \n\t" + ".word __kprobes_test_case_end_16 \n\t" + ); +} + +#endif + + +int kprobe_test_flags; +int kprobe_test_cc_position; + +static int test_try_count; +static int test_pass_count; +static int test_fail_count; + +static struct pt_regs initial_regs; +static struct pt_regs expected_regs; +static struct pt_regs result_regs; + +static u32 expected_memory[TEST_MEMORY_SIZE/sizeof(u32)]; + +static const char *current_title; +static struct test_arg *current_args; +static u32 *current_stack; +static uintptr_t current_branch_target; + +static uintptr_t current_code_start; +static kprobe_opcode_t current_instruction; + + +#define TEST_CASE_PASSED -1 +#define TEST_CASE_FAILED -2 + +static int test_case_run_count; +static bool test_case_is_thumb; +static int test_instance; + +/* + * We ignore the state of the imprecise abort disable flag (CPSR.A) because this + * can change randomly as the kernel doesn't take care to preserve or initialise + * this across context switches. Also, with Security Extentions, the flag may + * not be under control of the kernel; for this reason we ignore the state of + * the FIQ disable flag CPSR.F as well. + */ +#define PSR_IGNORE_BITS (PSR_A_BIT | PSR_F_BIT) + +static unsigned long test_check_cc(int cc, unsigned long cpsr) +{ + unsigned long temp; + + switch (cc) { + case 0x0: /* eq */ + return cpsr & PSR_Z_BIT; + + case 0x1: /* ne */ + return (~cpsr) & PSR_Z_BIT; + + case 0x2: /* cs */ + return cpsr & PSR_C_BIT; + + case 0x3: /* cc */ + return (~cpsr) & PSR_C_BIT; + + case 0x4: /* mi */ + return cpsr & PSR_N_BIT; + + case 0x5: /* pl */ + return (~cpsr) & PSR_N_BIT; + + case 0x6: /* vs */ + return cpsr & PSR_V_BIT; + + case 0x7: /* vc */ + return (~cpsr) & PSR_V_BIT; + + case 0x8: /* hi */ + cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */ + return cpsr & PSR_C_BIT; + + case 0x9: /* ls */ + cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */ + return (~cpsr) & PSR_C_BIT; + + case 0xa: /* ge */ + cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ + return (~cpsr) & PSR_N_BIT; + + case 0xb: /* lt */ + cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ + return cpsr & PSR_N_BIT; + + case 0xc: /* gt */ + temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ + temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */ + return (~temp) & PSR_N_BIT; + + case 0xd: /* le */ + temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ + temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */ + return temp & PSR_N_BIT; + + case 0xe: /* al */ + case 0xf: /* unconditional */ + return true; + } + BUG(); + return false; +} + +static int is_last_scenario; +static int probe_should_run; /* 0 = no, 1 = yes, -1 = unknown */ +static int memory_needs_checking; + +static unsigned long test_context_cpsr(int scenario) +{ + unsigned long cpsr; + + probe_should_run = 1; + + /* Default case is that we cycle through 16 combinations of flags */ + cpsr = (scenario & 0xf) << 28; /* N,Z,C,V flags */ + cpsr |= (scenario & 0xf) << 16; /* GE flags */ + cpsr |= (scenario & 0x1) << 27; /* Toggle Q flag */ + + if (!test_case_is_thumb) { + /* Testing ARM code */ + probe_should_run = test_check_cc(current_instruction >> 28, cpsr) != 0; + if (scenario == 15) + is_last_scenario = true; + + } else if (kprobe_test_flags & TEST_FLAG_NO_ITBLOCK) { + /* Testing Thumb code without setting ITSTATE */ + if (kprobe_test_cc_position) { + int cc = (current_instruction >> kprobe_test_cc_position) & 0xf; + probe_should_run = test_check_cc(cc, cpsr) != 0; + } + + if (scenario == 15) + is_last_scenario = true; + + } else if (kprobe_test_flags & TEST_FLAG_FULL_ITBLOCK) { + /* Testing Thumb code with all combinations of ITSTATE */ + unsigned x = (scenario >> 4); + unsigned cond_base = x % 7; /* ITSTATE<7:5> */ + unsigned mask = x / 7 + 2; /* ITSTATE<4:0>, bits reversed */ + + if (mask > 0x1f) { + /* Finish by testing state from instruction 'itt al' */ + cond_base = 7; + mask = 0x4; + if ((scenario & 0xf) == 0xf) + is_last_scenario = true; + } + + cpsr |= cond_base << 13; /* ITSTATE<7:5> */ + cpsr |= (mask & 0x1) << 12; /* ITSTATE<4> */ + cpsr |= (mask & 0x2) << 10; /* ITSTATE<3> */ + cpsr |= (mask & 0x4) << 8; /* ITSTATE<2> */ + cpsr |= (mask & 0x8) << 23; /* ITSTATE<1> */ + cpsr |= (mask & 0x10) << 21; /* ITSTATE<0> */ + + probe_should_run = test_check_cc((cpsr >> 12) & 0xf, cpsr) != 0; + + } else { + /* Testing Thumb code with several combinations of ITSTATE */ + switch (scenario) { + case 16: /* Clear NZCV flags and 'it eq' state (false as Z=0) */ + cpsr = 0x00000800; + probe_should_run = 0; + break; + case 17: /* Set NZCV flags and 'it vc' state (false as V=1) */ + cpsr = 0xf0007800; + probe_should_run = 0; + break; + case 18: /* Clear NZCV flags and 'it ls' state (true as C=0) */ + cpsr = 0x00009800; + break; + case 19: /* Set NZCV flags and 'it cs' state (true as C=1) */ + cpsr = 0xf0002800; + is_last_scenario = true; + break; + } + } + + return cpsr; +} + +static void setup_test_context(struct pt_regs *regs) +{ + int scenario = test_case_run_count>>1; + unsigned long val; + struct test_arg *args; + int i; + + is_last_scenario = false; + memory_needs_checking = false; + + /* Initialise test memory on stack */ + val = (scenario & 1) ? VALM : ~VALM; + for (i = 0; i < TEST_MEMORY_SIZE / sizeof(current_stack[0]); ++i) + current_stack[i] = val + (i << 8); + /* Put target of branch on stack for tests which load PC from memory */ + if (current_branch_target) + current_stack[15] = current_branch_target; + /* Put a value for SP on stack for tests which load SP from memory */ + current_stack[13] = (u32)current_stack + 120; + + /* Initialise register values to their default state */ + val = (scenario & 2) ? VALR : ~VALR; + for (i = 0; i < 13; ++i) + regs->uregs[i] = val ^ (i << 8); + regs->ARM_lr = val ^ (14 << 8); + regs->ARM_cpsr &= ~(APSR_MASK | PSR_IT_MASK); + regs->ARM_cpsr |= test_context_cpsr(scenario); + + /* Perform testcase specific register setup */ + args = current_args; + for (; args[0].type != ARG_TYPE_END; ++args) + switch (args[0].type) { + case ARG_TYPE_REG: { + struct test_arg_regptr *arg = + (struct test_arg_regptr *)args; + regs->uregs[arg->reg] = arg->val; + break; + } + case ARG_TYPE_PTR: { + struct test_arg_regptr *arg = + (struct test_arg_regptr *)args; + regs->uregs[arg->reg] = + (unsigned long)current_stack + arg->val; + memory_needs_checking = true; + break; + } + case ARG_TYPE_MEM: { + struct test_arg_mem *arg = (struct test_arg_mem *)args; + current_stack[arg->index] = arg->val; + break; + } + default: + break; + } +} + +struct test_probe { + struct kprobe kprobe; + bool registered; + int hit; +}; + +static void unregister_test_probe(struct test_probe *probe) +{ + if (probe->registered) { + unregister_kprobe(&probe->kprobe); + probe->kprobe.flags = 0; /* Clear disable flag to allow reuse */ + } + probe->registered = false; +} + +static int register_test_probe(struct test_probe *probe) +{ + int ret; + + if (probe->registered) + BUG(); + + ret = register_kprobe(&probe->kprobe); + if (ret >= 0) { + probe->registered = true; + probe->hit = -1; + } + return ret; +} + +static int __kprobes +test_before_pre_handler(struct kprobe *p, struct pt_regs *regs) +{ + container_of(p, struct test_probe, kprobe)->hit = test_instance; + return 0; +} + +static void __kprobes +test_before_post_handler(struct kprobe *p, struct pt_regs *regs, + unsigned long flags) +{ + setup_test_context(regs); + initial_regs = *regs; + initial_regs.ARM_cpsr &= ~PSR_IGNORE_BITS; +} + +static int __kprobes +test_case_pre_handler(struct kprobe *p, struct pt_regs *regs) +{ + container_of(p, struct test_probe, kprobe)->hit = test_instance; + return 0; +} + +static int __kprobes +test_after_pre_handler(struct kprobe *p, struct pt_regs *regs) +{ + if (container_of(p, struct test_probe, kprobe)->hit == test_instance) + return 0; /* Already run for this test instance */ + + result_regs = *regs; + result_regs.ARM_cpsr &= ~PSR_IGNORE_BITS; + + /* Undo any changes done to SP by the test case */ + regs->ARM_sp = (unsigned long)current_stack; + + container_of(p, struct test_probe, kprobe)->hit = test_instance; + return 0; +} + +static struct test_probe test_before_probe = { + .kprobe.pre_handler = test_before_pre_handler, + .kprobe.post_handler = test_before_post_handler, +}; + +static struct test_probe test_case_probe = { + .kprobe.pre_handler = test_case_pre_handler, +}; + +static struct test_probe test_after_probe = { + .kprobe.pre_handler = test_after_pre_handler, +}; + +static struct test_probe test_after2_probe = { + .kprobe.pre_handler = test_after_pre_handler, +}; + +static void test_case_cleanup(void) +{ + unregister_test_probe(&test_before_probe); + unregister_test_probe(&test_case_probe); + unregister_test_probe(&test_after_probe); + unregister_test_probe(&test_after2_probe); +} + +static void print_registers(struct pt_regs *regs) +{ + pr_err("r0 %08lx | r1 %08lx | r2 %08lx | r3 %08lx\n", + regs->ARM_r0, regs->ARM_r1, regs->ARM_r2, regs->ARM_r3); + pr_err("r4 %08lx | r5 %08lx | r6 %08lx | r7 %08lx\n", + regs->ARM_r4, regs->ARM_r5, regs->ARM_r6, regs->ARM_r7); + pr_err("r8 %08lx | r9 %08lx | r10 %08lx | r11 %08lx\n", + regs->ARM_r8, regs->ARM_r9, regs->ARM_r10, regs->ARM_fp); + pr_err("r12 %08lx | sp %08lx | lr %08lx | pc %08lx\n", + regs->ARM_ip, regs->ARM_sp, regs->ARM_lr, regs->ARM_pc); + pr_err("cpsr %08lx\n", regs->ARM_cpsr); +} + +static void print_memory(u32 *mem, size_t size) +{ + int i; + for (i = 0; i < size / sizeof(u32); i += 4) + pr_err("%08x %08x %08x %08x\n", mem[i], mem[i+1], + mem[i+2], mem[i+3]); +} + +static size_t expected_memory_size(u32 *sp) +{ + size_t size = sizeof(expected_memory); + int offset = (uintptr_t)sp - (uintptr_t)current_stack; + if (offset > 0) + size -= offset; + return size; +} + +static void test_case_failed(const char *message) +{ + test_case_cleanup(); + + pr_err("FAIL: %s\n", message); + pr_err("FAIL: Test %s\n", current_title); + pr_err("FAIL: Scenario %d\n", test_case_run_count >> 1); +} + +static unsigned long next_instruction(unsigned long pc) +{ +#ifdef CONFIG_THUMB2_KERNEL + if ((pc & 1) && !is_wide_instruction(*(u16 *)(pc - 1))) + return pc + 2; + else +#endif + return pc + 4; +} + +static uintptr_t __used kprobes_test_case_start(const char *title, void *stack) +{ + struct test_arg *args; + struct test_arg_end *end_arg; + unsigned long test_code; + + args = (struct test_arg *)PTR_ALIGN(title + strlen(title) + 1, 4); + + current_title = title; + current_args = args; + current_stack = stack; + + ++test_try_count; + + while (args->type != ARG_TYPE_END) + ++args; + end_arg = (struct test_arg_end *)args; + + test_code = (unsigned long)(args + 1); /* Code starts after args */ + + test_case_is_thumb = end_arg->flags & ARG_FLAG_THUMB; + if (test_case_is_thumb) + test_code |= 1; + + current_code_start = test_code; + + current_branch_target = 0; + if (end_arg->branch_offset != end_arg->end_offset) + current_branch_target = test_code + end_arg->branch_offset; + + test_code += end_arg->code_offset; + test_before_probe.kprobe.addr = (kprobe_opcode_t *)test_code; + + test_code = next_instruction(test_code); + test_case_probe.kprobe.addr = (kprobe_opcode_t *)test_code; + + if (test_case_is_thumb) { + u16 *p = (u16 *)(test_code & ~1); + current_instruction = p[0]; + if (is_wide_instruction(current_instruction)) { + current_instruction <<= 16; + current_instruction |= p[1]; + } + } else { + current_instruction = *(u32 *)test_code; + } + + if (current_title[0] == '.') + verbose("%s\n", current_title); + else + verbose("%s\t@ %0*x\n", current_title, + test_case_is_thumb ? 4 : 8, + current_instruction); + + test_code = next_instruction(test_code); + test_after_probe.kprobe.addr = (kprobe_opcode_t *)test_code; + + if (kprobe_test_flags & TEST_FLAG_NARROW_INSTR) { + if (!test_case_is_thumb || + is_wide_instruction(current_instruction)) { + test_case_failed("expected 16-bit instruction"); + goto fail; + } + } else { + if (test_case_is_thumb && + !is_wide_instruction(current_instruction)) { + test_case_failed("expected 32-bit instruction"); + goto fail; + } + } + + coverage_add(current_instruction); + + if (end_arg->flags & ARG_FLAG_UNSUPPORTED) { + if (register_test_probe(&test_case_probe) < 0) + goto pass; + test_case_failed("registered probe for unsupported instruction"); + goto fail; + } + + if (end_arg->flags & ARG_FLAG_SUPPORTED) { + if (register_test_probe(&test_case_probe) >= 0) + goto pass; + test_case_failed("couldn't register probe for supported instruction"); + goto fail; + } + + if (register_test_probe(&test_before_probe) < 0) { + test_case_failed("register test_before_probe failed"); + goto fail; + } + if (register_test_probe(&test_after_probe) < 0) { + test_case_failed("register test_after_probe failed"); + goto fail; + } + if (current_branch_target) { + test_after2_probe.kprobe.addr = + (kprobe_opcode_t *)current_branch_target; + if (register_test_probe(&test_after2_probe) < 0) { + test_case_failed("register test_after2_probe failed"); + goto fail; + } + } + + /* Start first run of test case */ + test_case_run_count = 0; + ++test_instance; + return current_code_start; +pass: + test_case_run_count = TEST_CASE_PASSED; + return (uintptr_t)test_after_probe.kprobe.addr; +fail: + test_case_run_count = TEST_CASE_FAILED; + return (uintptr_t)test_after_probe.kprobe.addr; +} + +static bool check_test_results(void) +{ + size_t mem_size = 0; + u32 *mem = 0; + + if (memcmp(&expected_regs, &result_regs, sizeof(expected_regs))) { + test_case_failed("registers differ"); + goto fail; + } + + if (memory_needs_checking) { + mem = (u32 *)result_regs.ARM_sp; + mem_size = expected_memory_size(mem); + if (memcmp(expected_memory, mem, mem_size)) { + test_case_failed("test memory differs"); + goto fail; + } + } + + return true; + +fail: + pr_err("initial_regs:\n"); + print_registers(&initial_regs); + pr_err("expected_regs:\n"); + print_registers(&expected_regs); + pr_err("result_regs:\n"); + print_registers(&result_regs); + + if (mem) { + pr_err("current_stack=%p\n", current_stack); + pr_err("expected_memory:\n"); + print_memory(expected_memory, mem_size); + pr_err("result_memory:\n"); + print_memory(mem, mem_size); + } + + return false; +} + +static uintptr_t __used kprobes_test_case_end(void) +{ + if (test_case_run_count < 0) { + if (test_case_run_count == TEST_CASE_PASSED) + /* kprobes_test_case_start did all the needed testing */ + goto pass; + else + /* kprobes_test_case_start failed */ + goto fail; + } + + if (test_before_probe.hit != test_instance) { + test_case_failed("test_before_handler not run"); + goto fail; + } + + if (test_after_probe.hit != test_instance && + test_after2_probe.hit != test_instance) { + test_case_failed("test_after_handler not run"); + goto fail; + } + + /* + * Even numbered test runs ran without a probe on the test case so + * we can gather reference results. The subsequent odd numbered run + * will have the probe inserted. + */ + if ((test_case_run_count & 1) == 0) { + /* Save results from run without probe */ + u32 *mem = (u32 *)result_regs.ARM_sp; + expected_regs = result_regs; + memcpy(expected_memory, mem, expected_memory_size(mem)); + + /* Insert probe onto test case instruction */ + if (register_test_probe(&test_case_probe) < 0) { + test_case_failed("register test_case_probe failed"); + goto fail; + } + } else { + /* Check probe ran as expected */ + if (probe_should_run == 1) { + if (test_case_probe.hit != test_instance) { + test_case_failed("test_case_handler not run"); + goto fail; + } + } else if (probe_should_run == 0) { + if (test_case_probe.hit == test_instance) { + test_case_failed("test_case_handler ran"); + goto fail; + } + } + + /* Remove probe for any subsequent reference run */ + unregister_test_probe(&test_case_probe); + + if (!check_test_results()) + goto fail; + + if (is_last_scenario) + goto pass; + } + + /* Do next test run */ + ++test_case_run_count; + ++test_instance; + return current_code_start; +fail: + ++test_fail_count; + goto end; +pass: + ++test_pass_count; +end: + test_case_cleanup(); + return 0; +} + + +/* + * Top level test functions + */ + +static int run_test_cases(void (*tests)(void), const union decode_item *table) +{ + int ret; + + pr_info(" Check decoding tables\n"); + ret = table_test(table); + if (ret) + return ret; + + pr_info(" Run test cases\n"); + ret = coverage_start(table); + if (ret) + return ret; + + tests(); + + coverage_end(); + return 0; +} + + +static int __init run_all_tests(void) +{ + int ret = 0; + + pr_info("Begining kprobe tests...\n"); + +#ifndef CONFIG_THUMB2_KERNEL + + pr_info("Probe ARM code\n"); + ret = run_api_tests(arm_func); + if (ret) + goto out; + + pr_info("ARM instruction simulation\n"); + ret = run_test_cases(kprobe_arm_test_cases, kprobe_decode_arm_table); + if (ret) + goto out; + +#else /* CONFIG_THUMB2_KERNEL */ + + pr_info("Probe 16-bit Thumb code\n"); + ret = run_api_tests(thumb16_func); + if (ret) + goto out; + + pr_info("Probe 32-bit Thumb code, even halfword\n"); + ret = run_api_tests(thumb32even_func); + if (ret) + goto out; + + pr_info("Probe 32-bit Thumb code, odd halfword\n"); + ret = run_api_tests(thumb32odd_func); + if (ret) + goto out; + + pr_info("16-bit Thumb instruction simulation\n"); + ret = run_test_cases(kprobe_thumb16_test_cases, + kprobe_decode_thumb16_table); + if (ret) + goto out; + + pr_info("32-bit Thumb instruction simulation\n"); + ret = run_test_cases(kprobe_thumb32_test_cases, + kprobe_decode_thumb32_table); + if (ret) + goto out; +#endif + + pr_info("Total instruction simulation tests=%d, pass=%d fail=%d\n", + test_try_count, test_pass_count, test_fail_count); + if (test_fail_count) { + ret = -EINVAL; + goto out; + } + +#if BENCHMARKING + pr_info("Benchmarks\n"); + ret = run_benchmarks(); + if (ret) + goto out; +#endif + +#if __LINUX_ARM_ARCH__ >= 7 + /* We are able to run all test cases so coverage should be complete */ + if (coverage_fail) { + pr_err("FAIL: Test coverage checks failed\n"); + ret = -EINVAL; + goto out; + } +#endif + +out: + if (ret == 0) + pr_info("Finished kprobe tests OK\n"); + else + pr_err("kprobe tests failed\n"); + + return ret; +} + + +/* + * Module setup + */ + +#ifdef MODULE + +static void __exit kprobe_test_exit(void) +{ +} + +module_init(run_all_tests) +module_exit(kprobe_test_exit) +MODULE_LICENSE("GPL"); + +#else /* !MODULE */ + +late_initcall(run_all_tests); + +#endif diff --git a/arch/arm/kernel/kprobes-test.h b/arch/arm/kernel/kprobes-test.h new file mode 100644 index 0000000000000000000000000000000000000000..0dc5d77b9356bcd86b4b0c087bf642bc6396e06e --- /dev/null +++ b/arch/arm/kernel/kprobes-test.h @@ -0,0 +1,392 @@ +/* + * arch/arm/kernel/kprobes-test.h + * + * Copyright (C) 2011 Jon Medhurst . + * + * 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. + */ + +#define VERBOSE 0 /* Set to '1' for more logging of test cases */ + +#ifdef CONFIG_THUMB2_KERNEL +#define NORMAL_ISA "16" +#else +#define NORMAL_ISA "32" +#endif + + +/* Flags used in kprobe_test_flags */ +#define TEST_FLAG_NO_ITBLOCK (1<<0) +#define TEST_FLAG_FULL_ITBLOCK (1<<1) +#define TEST_FLAG_NARROW_INSTR (1<<2) + +extern int kprobe_test_flags; +extern int kprobe_test_cc_position; + + +#define TEST_MEMORY_SIZE 256 + + +/* + * Test case structures. + * + * The arguments given to test cases can be one of three types. + * + * ARG_TYPE_REG + * Load a register with the given value. + * + * ARG_TYPE_PTR + * Load a register with a pointer into the stack buffer (SP + given value). + * + * ARG_TYPE_MEM + * Store the given value into the stack buffer at [SP+index]. + * + */ + +#define ARG_TYPE_END 0 +#define ARG_TYPE_REG 1 +#define ARG_TYPE_PTR 2 +#define ARG_TYPE_MEM 3 + +#define ARG_FLAG_UNSUPPORTED 0x01 +#define ARG_FLAG_SUPPORTED 0x02 +#define ARG_FLAG_THUMB 0x10 /* Must be 16 so TEST_ISA can be used */ +#define ARG_FLAG_ARM 0x20 /* Must be 32 so TEST_ISA can be used */ + +struct test_arg { + u8 type; /* ARG_TYPE_x */ + u8 _padding[7]; +}; + +struct test_arg_regptr { + u8 type; /* ARG_TYPE_REG or ARG_TYPE_PTR */ + u8 reg; + u8 _padding[2]; + u32 val; +}; + +struct test_arg_mem { + u8 type; /* ARG_TYPE_MEM */ + u8 index; + u8 _padding[2]; + u32 val; +}; + +struct test_arg_end { + u8 type; /* ARG_TYPE_END */ + u8 flags; /* ARG_FLAG_x */ + u16 code_offset; + u16 branch_offset; + u16 end_offset; +}; + + +/* + * Building blocks for test cases. + * + * Each test case is wrapped between TESTCASE_START and TESTCASE_END. + * + * To specify arguments for a test case the TEST_ARG_{REG,PTR,MEM} macros are + * used followed by a terminating TEST_ARG_END. + * + * After this, the instruction to be tested is defined with TEST_INSTRUCTION. + * Or for branches, TEST_BRANCH_B and TEST_BRANCH_F (branch forwards/backwards). + * + * Some specific test cases may make use of other custom constructs. + */ + +#if VERBOSE +#define verbose(fmt, ...) pr_info(fmt, ##__VA_ARGS__) +#else +#define verbose(fmt, ...) +#endif + +#define TEST_GROUP(title) \ + verbose("\n"); \ + verbose(title"\n"); \ + verbose("---------------------------------------------------------\n"); + +#define TESTCASE_START(title) \ + __asm__ __volatile__ ( \ + "bl __kprobes_test_case_start \n\t" \ + /* don't use .asciz here as 'title' may be */ \ + /* multiple strings to be concatenated. */ \ + ".ascii "#title" \n\t" \ + ".byte 0 \n\t" \ + ".align 2 \n\t" + +#define TEST_ARG_REG(reg, val) \ + ".byte "__stringify(ARG_TYPE_REG)" \n\t" \ + ".byte "#reg" \n\t" \ + ".short 0 \n\t" \ + ".word "#val" \n\t" + +#define TEST_ARG_PTR(reg, val) \ + ".byte "__stringify(ARG_TYPE_PTR)" \n\t" \ + ".byte "#reg" \n\t" \ + ".short 0 \n\t" \ + ".word "#val" \n\t" + +#define TEST_ARG_MEM(index, val) \ + ".byte "__stringify(ARG_TYPE_MEM)" \n\t" \ + ".byte "#index" \n\t" \ + ".short 0 \n\t" \ + ".word "#val" \n\t" + +#define TEST_ARG_END(flags) \ + ".byte "__stringify(ARG_TYPE_END)" \n\t" \ + ".byte "TEST_ISA flags" \n\t" \ + ".short 50f-0f \n\t" \ + ".short 2f-0f \n\t" \ + ".short 99f-0f \n\t" \ + ".code "TEST_ISA" \n\t" \ + "0: \n\t" + +#define TEST_INSTRUCTION(instruction) \ + "50: nop \n\t" \ + "1: "instruction" \n\t" \ + " nop \n\t" + +#define TEST_BRANCH_F(instruction, xtra_dist) \ + TEST_INSTRUCTION(instruction) \ + ".if "#xtra_dist" \n\t" \ + " b 99f \n\t" \ + ".space "#xtra_dist" \n\t" \ + ".endif \n\t" \ + " b 99f \n\t" \ + "2: nop \n\t" + +#define TEST_BRANCH_B(instruction, xtra_dist) \ + " b 50f \n\t" \ + " b 99f \n\t" \ + "2: nop \n\t" \ + " b 99f \n\t" \ + ".if "#xtra_dist" \n\t" \ + ".space "#xtra_dist" \n\t" \ + ".endif \n\t" \ + TEST_INSTRUCTION(instruction) + +#define TESTCASE_END \ + "2: \n\t" \ + "99: \n\t" \ + " bl __kprobes_test_case_end_"TEST_ISA" \n\t" \ + ".code "NORMAL_ISA" \n\t" \ + : : \ + : "r0", "r1", "r2", "r3", "ip", "lr", "memory", "cc" \ + ); + + +/* + * Macros to define test cases. + * + * Those of the form TEST_{R,P,M}* can be used to define test cases + * which take combinations of the three basic types of arguments. E.g. + * + * TEST_R One register argument + * TEST_RR Two register arguments + * TEST_RPR A register, a pointer, then a register argument + * + * For testing instructions which may branch, there are macros TEST_BF_* + * and TEST_BB_* for branching forwards and backwards. + * + * TEST_SUPPORTED and TEST_UNSUPPORTED don't cause the code to be executed, + * the just verify that a kprobe is or is not allowed on the given instruction. + */ + +#define TEST(code) \ + TESTCASE_START(code) \ + TEST_ARG_END("") \ + TEST_INSTRUCTION(code) \ + TESTCASE_END + +#define TEST_UNSUPPORTED(code) \ + TESTCASE_START(code) \ + TEST_ARG_END("|"__stringify(ARG_FLAG_UNSUPPORTED)) \ + TEST_INSTRUCTION(code) \ + TESTCASE_END + +#define TEST_SUPPORTED(code) \ + TESTCASE_START(code) \ + TEST_ARG_END("|"__stringify(ARG_FLAG_SUPPORTED)) \ + TEST_INSTRUCTION(code) \ + TESTCASE_END + +#define TEST_R(code1, reg, val, code2) \ + TESTCASE_START(code1 #reg code2) \ + TEST_ARG_REG(reg, val) \ + TEST_ARG_END("") \ + TEST_INSTRUCTION(code1 #reg code2) \ + TESTCASE_END + +#define TEST_RR(code1, reg1, val1, code2, reg2, val2, code3) \ + TESTCASE_START(code1 #reg1 code2 #reg2 code3) \ + TEST_ARG_REG(reg1, val1) \ + TEST_ARG_REG(reg2, val2) \ + TEST_ARG_END("") \ + TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3) \ + TESTCASE_END + +#define TEST_RRR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\ + TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4) \ + TEST_ARG_REG(reg1, val1) \ + TEST_ARG_REG(reg2, val2) \ + TEST_ARG_REG(reg3, val3) \ + TEST_ARG_END("") \ + TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4) \ + TESTCASE_END + +#define TEST_RRRR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4, reg4, val4) \ + TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4 #reg4) \ + TEST_ARG_REG(reg1, val1) \ + TEST_ARG_REG(reg2, val2) \ + TEST_ARG_REG(reg3, val3) \ + TEST_ARG_REG(reg4, val4) \ + TEST_ARG_END("") \ + TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4 #reg4) \ + TESTCASE_END + +#define TEST_P(code1, reg1, val1, code2) \ + TESTCASE_START(code1 #reg1 code2) \ + TEST_ARG_PTR(reg1, val1) \ + TEST_ARG_END("") \ + TEST_INSTRUCTION(code1 #reg1 code2) \ + TESTCASE_END + +#define TEST_PR(code1, reg1, val1, code2, reg2, val2, code3) \ + TESTCASE_START(code1 #reg1 code2 #reg2 code3) \ + TEST_ARG_PTR(reg1, val1) \ + TEST_ARG_REG(reg2, val2) \ + TEST_ARG_END("") \ + TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3) \ + TESTCASE_END + +#define TEST_RP(code1, reg1, val1, code2, reg2, val2, code3) \ + TESTCASE_START(code1 #reg1 code2 #reg2 code3) \ + TEST_ARG_REG(reg1, val1) \ + TEST_ARG_PTR(reg2, val2) \ + TEST_ARG_END("") \ + TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3) \ + TESTCASE_END + +#define TEST_PRR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\ + TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4) \ + TEST_ARG_PTR(reg1, val1) \ + TEST_ARG_REG(reg2, val2) \ + TEST_ARG_REG(reg3, val3) \ + TEST_ARG_END("") \ + TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4) \ + TESTCASE_END + +#define TEST_RPR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\ + TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4) \ + TEST_ARG_REG(reg1, val1) \ + TEST_ARG_PTR(reg2, val2) \ + TEST_ARG_REG(reg3, val3) \ + TEST_ARG_END("") \ + TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4) \ + TESTCASE_END + +#define TEST_RRP(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\ + TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4) \ + TEST_ARG_REG(reg1, val1) \ + TEST_ARG_REG(reg2, val2) \ + TEST_ARG_PTR(reg3, val3) \ + TEST_ARG_END("") \ + TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4) \ + TESTCASE_END + +#define TEST_BF_P(code1, reg1, val1, code2) \ + TESTCASE_START(code1 #reg1 code2) \ + TEST_ARG_PTR(reg1, val1) \ + TEST_ARG_END("") \ + TEST_BRANCH_F(code1 #reg1 code2, 0) \ + TESTCASE_END + +#define TEST_BF_X(code, xtra_dist) \ + TESTCASE_START(code) \ + TEST_ARG_END("") \ + TEST_BRANCH_F(code, xtra_dist) \ + TESTCASE_END + +#define TEST_BB_X(code, xtra_dist) \ + TESTCASE_START(code) \ + TEST_ARG_END("") \ + TEST_BRANCH_B(code, xtra_dist) \ + TESTCASE_END + +#define TEST_BF_RX(code1, reg, val, code2, xtra_dist) \ + TESTCASE_START(code1 #reg code2) \ + TEST_ARG_REG(reg, val) \ + TEST_ARG_END("") \ + TEST_BRANCH_F(code1 #reg code2, xtra_dist) \ + TESTCASE_END + +#define TEST_BB_RX(code1, reg, val, code2, xtra_dist) \ + TESTCASE_START(code1 #reg code2) \ + TEST_ARG_REG(reg, val) \ + TEST_ARG_END("") \ + TEST_BRANCH_B(code1 #reg code2, xtra_dist) \ + TESTCASE_END + +#define TEST_BF(code) TEST_BF_X(code, 0) +#define TEST_BB(code) TEST_BB_X(code, 0) + +#define TEST_BF_R(code1, reg, val, code2) TEST_BF_RX(code1, reg, val, code2, 0) +#define TEST_BB_R(code1, reg, val, code2) TEST_BB_RX(code1, reg, val, code2, 0) + +#define TEST_BF_RR(code1, reg1, val1, code2, reg2, val2, code3) \ + TESTCASE_START(code1 #reg1 code2 #reg2 code3) \ + TEST_ARG_REG(reg1, val1) \ + TEST_ARG_REG(reg2, val2) \ + TEST_ARG_END("") \ + TEST_BRANCH_F(code1 #reg1 code2 #reg2 code3, 0) \ + TESTCASE_END + +#define TEST_X(code, codex) \ + TESTCASE_START(code) \ + TEST_ARG_END("") \ + TEST_INSTRUCTION(code) \ + " b 99f \n\t" \ + " "codex" \n\t" \ + TESTCASE_END + +#define TEST_RX(code1, reg, val, code2, codex) \ + TESTCASE_START(code1 #reg code2) \ + TEST_ARG_REG(reg, val) \ + TEST_ARG_END("") \ + TEST_INSTRUCTION(code1 __stringify(reg) code2) \ + " b 99f \n\t" \ + " "codex" \n\t" \ + TESTCASE_END + +#define TEST_RRX(code1, reg1, val1, code2, reg2, val2, code3, codex) \ + TESTCASE_START(code1 #reg1 code2 #reg2 code3) \ + TEST_ARG_REG(reg1, val1) \ + TEST_ARG_REG(reg2, val2) \ + TEST_ARG_END("") \ + TEST_INSTRUCTION(code1 __stringify(reg1) code2 __stringify(reg2) code3) \ + " b 99f \n\t" \ + " "codex" \n\t" \ + TESTCASE_END + + +/* Various values used in test cases... */ +#define N(val) (val ^ 0xffffffff) +#define VAL1 0x12345678 +#define VAL2 N(VAL1) +#define VAL3 0xa5f801 +#define VAL4 N(VAL3) +#define VALM 0x456789ab +#define VALR 0xdeaddead +#define HH1 0x0123fecb +#define HH2 0xa9874567 + + +#ifdef CONFIG_THUMB2_KERNEL +void kprobe_thumb16_test_cases(void); +void kprobe_thumb32_test_cases(void); +#else +void kprobe_arm_test_cases(void); +#endif diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c index 902ca59e8b11ce3c87c917f7ccc513d8fdbb38e9..8f96ec778e8dd4537afab036cb8e28456b9f4e10 100644 --- a/arch/arm/kernel/kprobes-thumb.c +++ b/arch/arm/kernel/kprobes-thumb.c @@ -10,6 +10,7 @@ #include #include +#include #include "kprobes.h" @@ -943,6 +944,9 @@ const union decode_item kprobe_decode_thumb32_table[] = { */ DECODE_END }; +#ifdef CONFIG_ARM_KPROBES_TEST_MODULE +EXPORT_SYMBOL_GPL(kprobe_decode_thumb32_table); +#endif static void __kprobes t16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs) @@ -1423,6 +1427,9 @@ const union decode_item kprobe_decode_thumb16_table[] = { DECODE_END }; +#ifdef CONFIG_ARM_KPROBES_TEST_MODULE +EXPORT_SYMBOL_GPL(kprobe_decode_thumb16_table); +#endif static unsigned long __kprobes thumb_check_cc(unsigned long cpsr) { diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h index a6aeda0a6c7fb227e8637ef9fbd808981177244a..38945f78f9f1cea97a9607d9a1572b9e5184ad81 100644 --- a/arch/arm/kernel/kprobes.h +++ b/arch/arm/kernel/kprobes.h @@ -413,6 +413,14 @@ struct decode_reject { DECODE_HEADER(DECODE_TYPE_REJECT, _mask, _value, 0) +#ifdef CONFIG_THUMB2_KERNEL +extern const union decode_item kprobe_decode_thumb16_table[]; +extern const union decode_item kprobe_decode_thumb32_table[]; +#else +extern const union decode_item kprobe_decode_arm_table[]; +#endif + + int kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi, const union decode_item *table, bool thumb16); diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index e59bbd496c39174da0a6ee4094fe6f717df97a67..c1b4463dcc839c781004080d7426e78771bad15a 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c @@ -32,6 +32,24 @@ static atomic_t waiting_for_crash_ipi; int machine_kexec_prepare(struct kimage *image) { + unsigned long page_list; + void *reboot_code_buffer; + page_list = image->head & PAGE_MASK; + + reboot_code_buffer = page_address(image->control_code_page); + + /* Prepare parameters for reboot_code_buffer*/ + kexec_start_address = image->start; + kexec_indirection_page = page_list; + kexec_mach_type = machine_arch_type; + kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET; + + /* copy our kernel relocation code to the control code page */ + memcpy(reboot_code_buffer, + relocate_new_kernel, relocate_new_kernel_size); + + flush_icache_range((unsigned long) reboot_code_buffer, + (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE); return 0; } @@ -82,31 +100,14 @@ void (*kexec_reinit)(void); void machine_kexec(struct kimage *image) { - unsigned long page_list; unsigned long reboot_code_buffer_phys; void *reboot_code_buffer; - - page_list = image->head & PAGE_MASK; - /* we need both effective and real address here */ reboot_code_buffer_phys = page_to_pfn(image->control_code_page) << PAGE_SHIFT; reboot_code_buffer = page_address(image->control_code_page); - /* Prepare parameters for reboot_code_buffer*/ - kexec_start_address = image->start; - kexec_indirection_page = page_list; - kexec_mach_type = machine_arch_type; - kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET; - - /* copy our kernel relocation code to the control code page */ - memcpy(reboot_code_buffer, - relocate_new_kernel, relocate_new_kernel_size); - - - flush_icache_range((unsigned long) reboot_code_buffer, - (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE); printk(KERN_INFO "Bye!\n"); if (kexec_reinit) diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index cc2020c2c70977a4e95eaadad130c688514682e9..1e9be5d25e56adcddb8ea4cff5997fc1698e72ce 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -33,7 +33,7 @@ * recompiling the whole kernel when CONFIG_XIP_KERNEL is turned on/off. */ #undef MODULES_VADDR -#define MODULES_VADDR (((unsigned long)_etext + ~PGDIR_MASK) & PGDIR_MASK) +#define MODULES_VADDR (((unsigned long)_etext + ~PMD_MASK) & PMD_MASK) #endif #ifdef CONFIG_MMU diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index 53c9c2610cbc5f70d708707abf394286914043a0..e6e5d7c84f1a4330bc37e9516694f8d1797be8a9 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -12,6 +12,7 @@ */ #define pr_fmt(fmt) "hw perfevents: " fmt +#include #include #include #include @@ -26,16 +27,8 @@ #include #include -static struct platform_device *pmu_device; - -/* - * Hardware lock to serialize accesses to PMU registers. Needed for the - * read/modify/write sequences. - */ -static DEFINE_RAW_SPINLOCK(pmu_lock); - /* - * ARMv6 supports a maximum of 3 events, starting from index 1. If we add + * ARMv6 supports a maximum of 3 events, starting from index 0. If we add * another platform that supports more, we need to increase this to be the * largest of all platforms. * @@ -43,62 +36,24 @@ static DEFINE_RAW_SPINLOCK(pmu_lock); * cycle counter CCNT + 31 events counters CNT0..30. * Cortex-A8 has 1+4 counters, Cortex-A9 has 1+6 counters. */ -#define ARMPMU_MAX_HWEVENTS 33 +#define ARMPMU_MAX_HWEVENTS 32 -/* The events for a given CPU. */ -struct cpu_hw_events { - /* - * The events that are active on the CPU for the given index. Index 0 - * is reserved. - */ - struct perf_event *events[ARMPMU_MAX_HWEVENTS]; - - /* - * A 1 bit for an index indicates that the counter is being used for - * an event. A 0 means that the counter can be used. - */ - unsigned long used_mask[BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)]; +static DEFINE_PER_CPU(struct perf_event * [ARMPMU_MAX_HWEVENTS], hw_events); +static DEFINE_PER_CPU(unsigned long [BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)], used_mask); +static DEFINE_PER_CPU(struct pmu_hw_events, cpu_hw_events); - /* - * A 1 bit for an index indicates that the counter is actively being - * used. - */ - unsigned long active_mask[BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)]; -}; -static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events); - -struct arm_pmu { - enum arm_perf_pmu_ids id; - const char *name; - irqreturn_t (*handle_irq)(int irq_num, void *dev); - void (*enable)(struct hw_perf_event *evt, int idx); - void (*disable)(struct hw_perf_event *evt, int idx); - int (*get_event_idx)(struct cpu_hw_events *cpuc, - struct hw_perf_event *hwc); - u32 (*read_counter)(int idx); - void (*write_counter)(int idx, u32 val); - void (*start)(void); - void (*stop)(void); - void (*reset)(void *); - const unsigned (*cache_map)[PERF_COUNT_HW_CACHE_MAX] - [PERF_COUNT_HW_CACHE_OP_MAX] - [PERF_COUNT_HW_CACHE_RESULT_MAX]; - const unsigned (*event_map)[PERF_COUNT_HW_MAX]; - u32 raw_event_mask; - int num_events; - u64 max_period; -}; +#define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu)) /* Set at runtime when we know what CPU type we are. */ -static const struct arm_pmu *armpmu; +static struct arm_pmu *cpu_pmu; enum arm_perf_pmu_ids armpmu_get_pmu_id(void) { int id = -ENODEV; - if (armpmu != NULL) - id = armpmu->id; + if (cpu_pmu != NULL) + id = cpu_pmu->id; return id; } @@ -109,8 +64,8 @@ armpmu_get_max_events(void) { int max_events = 0; - if (armpmu != NULL) - max_events = armpmu->num_events; + if (cpu_pmu != NULL) + max_events = cpu_pmu->num_events; return max_events; } @@ -130,7 +85,11 @@ EXPORT_SYMBOL_GPL(perf_num_counters); #define CACHE_OP_UNSUPPORTED 0xFFFF static int -armpmu_map_cache_event(u64 config) +armpmu_map_cache_event(const unsigned (*cache_map) + [PERF_COUNT_HW_CACHE_MAX] + [PERF_COUNT_HW_CACHE_OP_MAX] + [PERF_COUNT_HW_CACHE_RESULT_MAX], + u64 config) { unsigned int cache_type, cache_op, cache_result, ret; @@ -146,7 +105,7 @@ armpmu_map_cache_event(u64 config) if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX) return -EINVAL; - ret = (int)(*armpmu->cache_map)[cache_type][cache_op][cache_result]; + ret = (int)(*cache_map)[cache_type][cache_op][cache_result]; if (ret == CACHE_OP_UNSUPPORTED) return -ENOENT; @@ -155,23 +114,46 @@ armpmu_map_cache_event(u64 config) } static int -armpmu_map_event(u64 config) +armpmu_map_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config) { - int mapping = (*armpmu->event_map)[config]; - return mapping == HW_OP_UNSUPPORTED ? -EOPNOTSUPP : mapping; + int mapping = (*event_map)[config]; + return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping; } static int -armpmu_map_raw_event(u64 config) +armpmu_map_raw_event(u32 raw_event_mask, u64 config) { - return (int)(config & armpmu->raw_event_mask); + return (int)(config & raw_event_mask); } -static int +static int map_cpu_event(struct perf_event *event, + const unsigned (*event_map)[PERF_COUNT_HW_MAX], + const unsigned (*cache_map) + [PERF_COUNT_HW_CACHE_MAX] + [PERF_COUNT_HW_CACHE_OP_MAX] + [PERF_COUNT_HW_CACHE_RESULT_MAX], + u32 raw_event_mask) +{ + u64 config = event->attr.config; + + switch (event->attr.type) { + case PERF_TYPE_HARDWARE: + return armpmu_map_event(event_map, config); + case PERF_TYPE_HW_CACHE: + return armpmu_map_cache_event(cache_map, config); + case PERF_TYPE_RAW: + return armpmu_map_raw_event(raw_event_mask, config); + } + + return -ENOENT; +} + +int armpmu_event_set_period(struct perf_event *event, struct hw_perf_event *hwc, int idx) { + struct arm_pmu *armpmu = to_arm_pmu(event->pmu); s64 left = local64_read(&hwc->period_left); s64 period = hwc->sample_period; int ret = 0; @@ -202,11 +184,12 @@ armpmu_event_set_period(struct perf_event *event, return ret; } -static u64 +u64 armpmu_event_update(struct perf_event *event, struct hw_perf_event *hwc, int idx, int overflow) { + struct arm_pmu *armpmu = to_arm_pmu(event->pmu); u64 delta, prev_raw_count, new_raw_count; again: @@ -246,11 +229,9 @@ armpmu_read(struct perf_event *event) static void armpmu_stop(struct perf_event *event, int flags) { + struct arm_pmu *armpmu = to_arm_pmu(event->pmu); struct hw_perf_event *hwc = &event->hw; - if (!armpmu) - return; - /* * ARM pmu always has to update the counter, so ignore * PERF_EF_UPDATE, see comments in armpmu_start(). @@ -266,11 +247,9 @@ armpmu_stop(struct perf_event *event, int flags) static void armpmu_start(struct perf_event *event, int flags) { + struct arm_pmu *armpmu = to_arm_pmu(event->pmu); struct hw_perf_event *hwc = &event->hw; - if (!armpmu) - return; - /* * ARM pmu always has to reprogram the period, so ignore * PERF_EF_RELOAD, see the comment below. @@ -293,16 +272,16 @@ armpmu_start(struct perf_event *event, int flags) static void armpmu_del(struct perf_event *event, int flags) { - struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + struct arm_pmu *armpmu = to_arm_pmu(event->pmu); + struct pmu_hw_events *hw_events = armpmu->get_hw_events(); struct hw_perf_event *hwc = &event->hw; int idx = hwc->idx; WARN_ON(idx < 0); - clear_bit(idx, cpuc->active_mask); armpmu_stop(event, PERF_EF_UPDATE); - cpuc->events[idx] = NULL; - clear_bit(idx, cpuc->used_mask); + hw_events->events[idx] = NULL; + clear_bit(idx, hw_events->used_mask); perf_event_update_userpage(event); } @@ -310,7 +289,8 @@ armpmu_del(struct perf_event *event, int flags) static int armpmu_add(struct perf_event *event, int flags) { - struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + struct arm_pmu *armpmu = to_arm_pmu(event->pmu); + struct pmu_hw_events *hw_events = armpmu->get_hw_events(); struct hw_perf_event *hwc = &event->hw; int idx; int err = 0; @@ -318,7 +298,7 @@ armpmu_add(struct perf_event *event, int flags) perf_pmu_disable(event->pmu); /* If we don't have a space for the counter then finish early. */ - idx = armpmu->get_event_idx(cpuc, hwc); + idx = armpmu->get_event_idx(hw_events, hwc); if (idx < 0) { err = idx; goto out; @@ -330,8 +310,7 @@ armpmu_add(struct perf_event *event, int flags) */ event->hw.idx = idx; armpmu->disable(hwc, idx); - cpuc->events[idx] = event; - set_bit(idx, cpuc->active_mask); + hw_events->events[idx] = event; hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE; if (flags & PERF_EF_START) @@ -345,25 +324,25 @@ armpmu_add(struct perf_event *event, int flags) return err; } -static struct pmu pmu; - static int -validate_event(struct cpu_hw_events *cpuc, +validate_event(struct pmu_hw_events *hw_events, struct perf_event *event) { + struct arm_pmu *armpmu = to_arm_pmu(event->pmu); struct hw_perf_event fake_event = event->hw; + struct pmu *leader_pmu = event->group_leader->pmu; - if (event->pmu != &pmu || event->state <= PERF_EVENT_STATE_OFF) + if (event->pmu != leader_pmu || event->state <= PERF_EVENT_STATE_OFF) return 1; - return armpmu->get_event_idx(cpuc, &fake_event) >= 0; + return armpmu->get_event_idx(hw_events, &fake_event) >= 0; } static int validate_group(struct perf_event *event) { struct perf_event *sibling, *leader = event->group_leader; - struct cpu_hw_events fake_pmu; + struct pmu_hw_events fake_pmu; memset(&fake_pmu, 0, sizeof(fake_pmu)); @@ -383,110 +362,119 @@ validate_group(struct perf_event *event) static irqreturn_t armpmu_platform_irq(int irq, void *dev) { - struct arm_pmu_platdata *plat = dev_get_platdata(&pmu_device->dev); + struct arm_pmu *armpmu = (struct arm_pmu *) dev; + struct platform_device *plat_device = armpmu->plat_device; + struct arm_pmu_platdata *plat = dev_get_platdata(&plat_device->dev); return plat->handle_irq(irq, dev, armpmu->handle_irq); } +static void +armpmu_release_hardware(struct arm_pmu *armpmu) +{ + int i, irq, irqs; + struct platform_device *pmu_device = armpmu->plat_device; + + irqs = min(pmu_device->num_resources, num_possible_cpus()); + + for (i = 0; i < irqs; ++i) { + if (!cpumask_test_and_clear_cpu(i, &armpmu->active_irqs)) + continue; + irq = platform_get_irq(pmu_device, i); + if (irq >= 0) + free_irq(irq, armpmu); + } + + release_pmu(armpmu->type); +} + static int -armpmu_reserve_hardware(void) +armpmu_reserve_hardware(struct arm_pmu *armpmu) { struct arm_pmu_platdata *plat; irq_handler_t handle_irq; - int i, err = -ENODEV, irq; + int i, err, irq, irqs; + struct platform_device *pmu_device = armpmu->plat_device; - pmu_device = reserve_pmu(ARM_PMU_DEVICE_CPU); - if (IS_ERR(pmu_device)) { + err = reserve_pmu(armpmu->type); + if (err) { pr_warning("unable to reserve pmu\n"); - return PTR_ERR(pmu_device); + return err; } - init_pmu(ARM_PMU_DEVICE_CPU); - plat = dev_get_platdata(&pmu_device->dev); if (plat && plat->handle_irq) handle_irq = armpmu_platform_irq; else handle_irq = armpmu->handle_irq; - if (pmu_device->num_resources < 1) { + irqs = min(pmu_device->num_resources, num_possible_cpus()); + if (irqs < 1) { pr_err("no irqs for PMUs defined\n"); return -ENODEV; } - for (i = 0; i < pmu_device->num_resources; ++i) { + for (i = 0; i < irqs; ++i) { + err = 0; irq = platform_get_irq(pmu_device, i); if (irq < 0) continue; + /* + * If we have a single PMU interrupt that we can't shift, + * assume that we're running on a uniprocessor machine and + * continue. Otherwise, continue without this interrupt. + */ + if (irq_set_affinity(irq, cpumask_of(i)) && irqs > 1) { + pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n", + irq, i); + continue; + } + err = request_irq(irq, handle_irq, IRQF_DISABLED | IRQF_NOBALANCING, - "armpmu", NULL); + "arm-pmu", armpmu); if (err) { - pr_warning("unable to request IRQ%d for ARM perf " - "counters\n", irq); - break; + pr_err("unable to request IRQ%d for ARM PMU counters\n", + irq); + armpmu_release_hardware(armpmu); + return err; } - } - if (err) { - for (i = i - 1; i >= 0; --i) { - irq = platform_get_irq(pmu_device, i); - if (irq >= 0) - free_irq(irq, NULL); - } - release_pmu(ARM_PMU_DEVICE_CPU); - pmu_device = NULL; + cpumask_set_cpu(i, &armpmu->active_irqs); } - return err; + return 0; } static void -armpmu_release_hardware(void) +hw_perf_event_destroy(struct perf_event *event) { - int i, irq; + struct arm_pmu *armpmu = to_arm_pmu(event->pmu); + atomic_t *active_events = &armpmu->active_events; + struct mutex *pmu_reserve_mutex = &armpmu->reserve_mutex; - for (i = pmu_device->num_resources - 1; i >= 0; --i) { - irq = platform_get_irq(pmu_device, i); - if (irq >= 0) - free_irq(irq, NULL); + if (atomic_dec_and_mutex_lock(active_events, pmu_reserve_mutex)) { + armpmu_release_hardware(armpmu); + mutex_unlock(pmu_reserve_mutex); } - armpmu->stop(); - - release_pmu(ARM_PMU_DEVICE_CPU); - pmu_device = NULL; } -static atomic_t active_events = ATOMIC_INIT(0); -static DEFINE_MUTEX(pmu_reserve_mutex); - -static void -hw_perf_event_destroy(struct perf_event *event) +static int +event_requires_mode_exclusion(struct perf_event_attr *attr) { - if (atomic_dec_and_mutex_lock(&active_events, &pmu_reserve_mutex)) { - armpmu_release_hardware(); - mutex_unlock(&pmu_reserve_mutex); - } + return attr->exclude_idle || attr->exclude_user || + attr->exclude_kernel || attr->exclude_hv; } static int __hw_perf_event_init(struct perf_event *event) { + struct arm_pmu *armpmu = to_arm_pmu(event->pmu); struct hw_perf_event *hwc = &event->hw; int mapping, err; - /* Decode the generic type into an ARM event identifier. */ - if (PERF_TYPE_HARDWARE == event->attr.type) { - mapping = armpmu_map_event(event->attr.config); - } else if (PERF_TYPE_HW_CACHE == event->attr.type) { - mapping = armpmu_map_cache_event(event->attr.config); - } else if (PERF_TYPE_RAW == event->attr.type) { - mapping = armpmu_map_raw_event(event->attr.config); - } else { - pr_debug("event type %x not supported\n", event->attr.type); - return -EOPNOTSUPP; - } + mapping = armpmu->map_event(event); if (mapping < 0) { pr_debug("event %x:%llx not supported\n", event->attr.type, @@ -494,35 +482,32 @@ __hw_perf_event_init(struct perf_event *event) return mapping; } + /* + * We don't assign an index until we actually place the event onto + * hardware. Use -1 to signify that we haven't decided where to put it + * yet. For SMP systems, each core has it's own PMU so we can't do any + * clever allocation or constraints checking at this point. + */ + hwc->idx = -1; + hwc->config_base = 0; + hwc->config = 0; + hwc->event_base = 0; + /* * Check whether we need to exclude the counter from certain modes. - * The ARM performance counters are on all of the time so if someone - * has asked us for some excludes then we have to fail. */ - if (event->attr.exclude_kernel || event->attr.exclude_user || - event->attr.exclude_hv || event->attr.exclude_idle) { + if ((!armpmu->set_event_filter || + armpmu->set_event_filter(hwc, &event->attr)) && + event_requires_mode_exclusion(&event->attr)) { pr_debug("ARM performance counters do not support " "mode exclusion\n"); return -EPERM; } /* - * We don't assign an index until we actually place the event onto - * hardware. Use -1 to signify that we haven't decided where to put it - * yet. For SMP systems, each core has it's own PMU so we can't do any - * clever allocation or constraints checking at this point. + * Store the event encoding into the config_base field. */ - hwc->idx = -1; - - /* - * Store the event encoding into the config_base field. config and - * event_base are unused as the only 2 things we need to know are - * the event mapping and the counter to use. The counter to use is - * also the indx and the config_base is the event type. - */ - hwc->config_base = (unsigned long)mapping; - hwc->config = 0; - hwc->event_base = 0; + hwc->config_base |= (unsigned long)mapping; if (!hwc->sample_period) { hwc->sample_period = armpmu->max_period; @@ -542,32 +527,23 @@ __hw_perf_event_init(struct perf_event *event) static int armpmu_event_init(struct perf_event *event) { + struct arm_pmu *armpmu = to_arm_pmu(event->pmu); int err = 0; + atomic_t *active_events = &armpmu->active_events; - switch (event->attr.type) { - case PERF_TYPE_RAW: - case PERF_TYPE_HARDWARE: - case PERF_TYPE_HW_CACHE: - break; - - default: + if (armpmu->map_event(event) == -ENOENT) return -ENOENT; - } - - if (!armpmu) - return -ENODEV; event->destroy = hw_perf_event_destroy; - if (!atomic_inc_not_zero(&active_events)) { - mutex_lock(&pmu_reserve_mutex); - if (atomic_read(&active_events) == 0) { - err = armpmu_reserve_hardware(); - } + if (!atomic_inc_not_zero(active_events)) { + mutex_lock(&armpmu->reserve_mutex); + if (atomic_read(active_events) == 0) + err = armpmu_reserve_hardware(armpmu); if (!err) - atomic_inc(&active_events); - mutex_unlock(&pmu_reserve_mutex); + atomic_inc(active_events); + mutex_unlock(&armpmu->reserve_mutex); } if (err) @@ -582,22 +558,9 @@ static int armpmu_event_init(struct perf_event *event) static void armpmu_enable(struct pmu *pmu) { - /* Enable all of the perf events on hardware. */ - int idx, enabled = 0; - struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); - - if (!armpmu) - return; - - for (idx = 0; idx <= armpmu->num_events; ++idx) { - struct perf_event *event = cpuc->events[idx]; - - if (!event) - continue; - - armpmu->enable(&event->hw, idx); - enabled = 1; - } + struct arm_pmu *armpmu = to_arm_pmu(pmu); + struct pmu_hw_events *hw_events = armpmu->get_hw_events(); + int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events); if (enabled) armpmu->start(); @@ -605,20 +568,32 @@ static void armpmu_enable(struct pmu *pmu) static void armpmu_disable(struct pmu *pmu) { - if (armpmu) - armpmu->stop(); + struct arm_pmu *armpmu = to_arm_pmu(pmu); + armpmu->stop(); } -static struct pmu pmu = { - .pmu_enable = armpmu_enable, - .pmu_disable = armpmu_disable, - .event_init = armpmu_event_init, - .add = armpmu_add, - .del = armpmu_del, - .start = armpmu_start, - .stop = armpmu_stop, - .read = armpmu_read, -}; +static void __init armpmu_init(struct arm_pmu *armpmu) +{ + atomic_set(&armpmu->active_events, 0); + mutex_init(&armpmu->reserve_mutex); + + armpmu->pmu = (struct pmu) { + .pmu_enable = armpmu_enable, + .pmu_disable = armpmu_disable, + .event_init = armpmu_event_init, + .add = armpmu_add, + .del = armpmu_del, + .start = armpmu_start, + .stop = armpmu_stop, + .read = armpmu_read, + }; +} + +int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type) +{ + armpmu_init(armpmu); + return perf_pmu_register(&armpmu->pmu, name, type); +} /* Include the PMU-specific implementations. */ #include "perf_event_xscale.c" @@ -630,14 +605,72 @@ static struct pmu pmu = { * This requires SMP to be available, so exists as a separate initcall. */ static int __init -armpmu_reset(void) +cpu_pmu_reset(void) +{ + if (cpu_pmu && cpu_pmu->reset) + return on_each_cpu(cpu_pmu->reset, NULL, 1); + return 0; +} +arch_initcall(cpu_pmu_reset); + +/* + * PMU platform driver and devicetree bindings. + */ +static struct of_device_id armpmu_of_device_ids[] = { + {.compatible = "arm,cortex-a9-pmu"}, + {.compatible = "arm,cortex-a8-pmu"}, + {.compatible = "arm,arm1136-pmu"}, + {.compatible = "arm,arm1176-pmu"}, + {}, +}; + +static struct platform_device_id armpmu_plat_device_ids[] = { + {.name = "arm-pmu"}, + {}, +}; + +static int __devinit armpmu_device_probe(struct platform_device *pdev) { - if (armpmu && armpmu->reset) - return on_each_cpu(armpmu->reset, NULL, 1); + cpu_pmu->plat_device = pdev; return 0; } -arch_initcall(armpmu_reset); +static struct platform_driver armpmu_driver = { + .driver = { + .name = "arm-pmu", + .of_match_table = armpmu_of_device_ids, + }, + .probe = armpmu_device_probe, + .id_table = armpmu_plat_device_ids, +}; + +static int __init register_pmu_driver(void) +{ + return platform_driver_register(&armpmu_driver); +} +device_initcall(register_pmu_driver); + +static struct pmu_hw_events *armpmu_get_cpu_events(void) +{ + return &__get_cpu_var(cpu_hw_events); +} + +static void __init cpu_pmu_init(struct arm_pmu *armpmu) +{ + int cpu; + for_each_possible_cpu(cpu) { + struct pmu_hw_events *events = &per_cpu(cpu_hw_events, cpu); + events->events = per_cpu(hw_events, cpu); + events->used_mask = per_cpu(used_mask, cpu); + raw_spin_lock_init(&events->pmu_lock); + } + armpmu->get_hw_events = armpmu_get_cpu_events; + armpmu->type = ARM_PMU_DEVICE_CPU; +} + +/* + * CPU PMU identification and registration. + */ static int __init init_hw_perf_events(void) { @@ -651,22 +684,22 @@ init_hw_perf_events(void) case 0xB360: /* ARM1136 */ case 0xB560: /* ARM1156 */ case 0xB760: /* ARM1176 */ - armpmu = armv6pmu_init(); + cpu_pmu = armv6pmu_init(); break; case 0xB020: /* ARM11mpcore */ - armpmu = armv6mpcore_pmu_init(); + cpu_pmu = armv6mpcore_pmu_init(); break; case 0xC080: /* Cortex-A8 */ - armpmu = armv7_a8_pmu_init(); + cpu_pmu = armv7_a8_pmu_init(); break; case 0xC090: /* Cortex-A9 */ - armpmu = armv7_a9_pmu_init(); + cpu_pmu = armv7_a9_pmu_init(); break; case 0xC050: /* Cortex-A5 */ - armpmu = armv7_a5_pmu_init(); + cpu_pmu = armv7_a5_pmu_init(); break; case 0xC0F0: /* Cortex-A15 */ - armpmu = armv7_a15_pmu_init(); + cpu_pmu = armv7_a15_pmu_init(); break; } /* Intel CPUs [xscale]. */ @@ -674,23 +707,23 @@ init_hw_perf_events(void) part_number = (cpuid >> 13) & 0x7; switch (part_number) { case 1: - armpmu = xscale1pmu_init(); + cpu_pmu = xscale1pmu_init(); break; case 2: - armpmu = xscale2pmu_init(); + cpu_pmu = xscale2pmu_init(); break; } } - if (armpmu) { + if (cpu_pmu) { pr_info("enabled with %s PMU driver, %d counters available\n", - armpmu->name, armpmu->num_events); + cpu_pmu->name, cpu_pmu->num_events); + cpu_pmu_init(cpu_pmu); + armpmu_register(cpu_pmu, "cpu", PERF_TYPE_RAW); } else { pr_info("no hardware support available\n"); } - perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW); - return 0; } early_initcall(init_hw_perf_events); diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c index dd7f3b9f4cb31bffbab806e75bc2c447cc9142fe..e63d8115c01b2fc9cabef9a23749cdc60e9ad0e7 100644 --- a/arch/arm/kernel/perf_event_v6.c +++ b/arch/arm/kernel/perf_event_v6.c @@ -54,7 +54,7 @@ enum armv6_perf_types { }; enum armv6_counters { - ARMV6_CYCLE_COUNTER = 1, + ARMV6_CYCLE_COUNTER = 0, ARMV6_COUNTER0, ARMV6_COUNTER1, }; @@ -433,6 +433,7 @@ armv6pmu_enable_event(struct hw_perf_event *hwc, int idx) { unsigned long val, mask, evt, flags; + struct pmu_hw_events *events = cpu_pmu->get_hw_events(); if (ARMV6_CYCLE_COUNTER == idx) { mask = 0; @@ -454,12 +455,29 @@ armv6pmu_enable_event(struct hw_perf_event *hwc, * Mask out the current event and set the counter to count the event * that we're interested in. */ - raw_spin_lock_irqsave(&pmu_lock, flags); + raw_spin_lock_irqsave(&events->pmu_lock, flags); val = armv6_pmcr_read(); val &= ~mask; val |= evt; armv6_pmcr_write(val); - raw_spin_unlock_irqrestore(&pmu_lock, flags); + raw_spin_unlock_irqrestore(&events->pmu_lock, flags); +} + +static int counter_is_active(unsigned long pmcr, int idx) +{ + unsigned long mask = 0; + if (idx == ARMV6_CYCLE_COUNTER) + mask = ARMV6_PMCR_CCOUNT_IEN; + else if (idx == ARMV6_COUNTER0) + mask = ARMV6_PMCR_COUNT0_IEN; + else if (idx == ARMV6_COUNTER1) + mask = ARMV6_PMCR_COUNT1_IEN; + + if (mask) + return pmcr & mask; + + WARN_ONCE(1, "invalid counter number (%d)\n", idx); + return 0; } static irqreturn_t @@ -468,7 +486,7 @@ armv6pmu_handle_irq(int irq_num, { unsigned long pmcr = armv6_pmcr_read(); struct perf_sample_data data; - struct cpu_hw_events *cpuc; + struct pmu_hw_events *cpuc; struct pt_regs *regs; int idx; @@ -487,11 +505,11 @@ armv6pmu_handle_irq(int irq_num, perf_sample_data_init(&data, 0); cpuc = &__get_cpu_var(cpu_hw_events); - for (idx = 0; idx <= armpmu->num_events; ++idx) { + for (idx = 0; idx < cpu_pmu->num_events; ++idx) { struct perf_event *event = cpuc->events[idx]; struct hw_perf_event *hwc; - if (!test_bit(idx, cpuc->active_mask)) + if (!counter_is_active(pmcr, idx)) continue; /* @@ -508,7 +526,7 @@ armv6pmu_handle_irq(int irq_num, continue; if (perf_event_overflow(event, &data, regs)) - armpmu->disable(hwc, idx); + cpu_pmu->disable(hwc, idx); } /* @@ -527,28 +545,30 @@ static void armv6pmu_start(void) { unsigned long flags, val; + struct pmu_hw_events *events = cpu_pmu->get_hw_events(); - raw_spin_lock_irqsave(&pmu_lock, flags); + raw_spin_lock_irqsave(&events->pmu_lock, flags); val = armv6_pmcr_read(); val |= ARMV6_PMCR_ENABLE; armv6_pmcr_write(val); - raw_spin_unlock_irqrestore(&pmu_lock, flags); + raw_spin_unlock_irqrestore(&events->pmu_lock, flags); } static void armv6pmu_stop(void) { unsigned long flags, val; + struct pmu_hw_events *events = cpu_pmu->get_hw_events(); - raw_spin_lock_irqsave(&pmu_lock, flags); + raw_spin_lock_irqsave(&events->pmu_lock, flags); val = armv6_pmcr_read(); val &= ~ARMV6_PMCR_ENABLE; armv6_pmcr_write(val); - raw_spin_unlock_irqrestore(&pmu_lock, flags); + raw_spin_unlock_irqrestore(&events->pmu_lock, flags); } static int -armv6pmu_get_event_idx(struct cpu_hw_events *cpuc, +armv6pmu_get_event_idx(struct pmu_hw_events *cpuc, struct hw_perf_event *event) { /* Always place a cycle counter into the cycle counter. */ @@ -578,6 +598,7 @@ armv6pmu_disable_event(struct hw_perf_event *hwc, int idx) { unsigned long val, mask, evt, flags; + struct pmu_hw_events *events = cpu_pmu->get_hw_events(); if (ARMV6_CYCLE_COUNTER == idx) { mask = ARMV6_PMCR_CCOUNT_IEN; @@ -598,12 +619,12 @@ armv6pmu_disable_event(struct hw_perf_event *hwc, * of ETM bus signal assertion cycles. The external reporting should * be disabled and so this should never increment. */ - raw_spin_lock_irqsave(&pmu_lock, flags); + raw_spin_lock_irqsave(&events->pmu_lock, flags); val = armv6_pmcr_read(); val &= ~mask; val |= evt; armv6_pmcr_write(val); - raw_spin_unlock_irqrestore(&pmu_lock, flags); + raw_spin_unlock_irqrestore(&events->pmu_lock, flags); } static void @@ -611,6 +632,7 @@ armv6mpcore_pmu_disable_event(struct hw_perf_event *hwc, int idx) { unsigned long val, mask, flags, evt = 0; + struct pmu_hw_events *events = cpu_pmu->get_hw_events(); if (ARMV6_CYCLE_COUNTER == idx) { mask = ARMV6_PMCR_CCOUNT_IEN; @@ -627,15 +649,21 @@ armv6mpcore_pmu_disable_event(struct hw_perf_event *hwc, * Unlike UP ARMv6, we don't have a way of stopping the counters. We * simply disable the interrupt reporting. */ - raw_spin_lock_irqsave(&pmu_lock, flags); + raw_spin_lock_irqsave(&events->pmu_lock, flags); val = armv6_pmcr_read(); val &= ~mask; val |= evt; armv6_pmcr_write(val); - raw_spin_unlock_irqrestore(&pmu_lock, flags); + raw_spin_unlock_irqrestore(&events->pmu_lock, flags); +} + +static int armv6_map_event(struct perf_event *event) +{ + return map_cpu_event(event, &armv6_perf_map, + &armv6_perf_cache_map, 0xFF); } -static const struct arm_pmu armv6pmu = { +static struct arm_pmu armv6pmu = { .id = ARM_PERF_PMU_ID_V6, .name = "v6", .handle_irq = armv6pmu_handle_irq, @@ -646,14 +674,12 @@ static const struct arm_pmu armv6pmu = { .get_event_idx = armv6pmu_get_event_idx, .start = armv6pmu_start, .stop = armv6pmu_stop, - .cache_map = &armv6_perf_cache_map, - .event_map = &armv6_perf_map, - .raw_event_mask = 0xFF, + .map_event = armv6_map_event, .num_events = 3, .max_period = (1LLU << 32) - 1, }; -static const struct arm_pmu *__init armv6pmu_init(void) +static struct arm_pmu *__init armv6pmu_init(void) { return &armv6pmu; } @@ -665,7 +691,14 @@ static const struct arm_pmu *__init armv6pmu_init(void) * disable the interrupt reporting and update the event. When unthrottling we * reset the period and enable the interrupt reporting. */ -static const struct arm_pmu armv6mpcore_pmu = { + +static int armv6mpcore_map_event(struct perf_event *event) +{ + return map_cpu_event(event, &armv6mpcore_perf_map, + &armv6mpcore_perf_cache_map, 0xFF); +} + +static struct arm_pmu armv6mpcore_pmu = { .id = ARM_PERF_PMU_ID_V6MP, .name = "v6mpcore", .handle_irq = armv6pmu_handle_irq, @@ -676,24 +709,22 @@ static const struct arm_pmu armv6mpcore_pmu = { .get_event_idx = armv6pmu_get_event_idx, .start = armv6pmu_start, .stop = armv6pmu_stop, - .cache_map = &armv6mpcore_perf_cache_map, - .event_map = &armv6mpcore_perf_map, - .raw_event_mask = 0xFF, + .map_event = armv6mpcore_map_event, .num_events = 3, .max_period = (1LLU << 32) - 1, }; -static const struct arm_pmu *__init armv6mpcore_pmu_init(void) +static struct arm_pmu *__init armv6mpcore_pmu_init(void) { return &armv6mpcore_pmu; } #else -static const struct arm_pmu *__init armv6pmu_init(void) +static struct arm_pmu *__init armv6pmu_init(void) { return NULL; } -static const struct arm_pmu *__init armv6mpcore_pmu_init(void) +static struct arm_pmu *__init armv6mpcore_pmu_init(void) { return NULL; } diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c index 6be3e2e4d838d030d37b10aa7db4dbbc92f75f82..1ef6d0034b85d1172c8efe1d1659e82dbced1032 100644 --- a/arch/arm/kernel/perf_event_v7.c +++ b/arch/arm/kernel/perf_event_v7.c @@ -17,6 +17,9 @@ */ #ifdef CONFIG_CPU_V7 + +static struct arm_pmu armv7pmu; + /* * Common ARMv7 event types * @@ -676,23 +679,24 @@ static const unsigned armv7_a15_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] }; /* - * Perf Events counters + * Perf Events' indices */ -enum armv7_counters { - ARMV7_CYCLE_COUNTER = 1, /* Cycle counter */ - ARMV7_COUNTER0 = 2, /* First event counter */ -}; +#define ARMV7_IDX_CYCLE_COUNTER 0 +#define ARMV7_IDX_COUNTER0 1 +#define ARMV7_IDX_COUNTER_LAST (ARMV7_IDX_CYCLE_COUNTER + cpu_pmu->num_events - 1) + +#define ARMV7_MAX_COUNTERS 32 +#define ARMV7_COUNTER_MASK (ARMV7_MAX_COUNTERS - 1) /* - * The cycle counter is ARMV7_CYCLE_COUNTER. - * The first event counter is ARMV7_COUNTER0. - * The last event counter is (ARMV7_COUNTER0 + armpmu->num_events - 1). + * ARMv7 low level PMNC access */ -#define ARMV7_COUNTER_LAST (ARMV7_COUNTER0 + armpmu->num_events - 1) /* - * ARMv7 low level PMNC access + * Perf Event to low level counters mapping */ +#define ARMV7_IDX_TO_COUNTER(x) \ + (((x) - ARMV7_IDX_COUNTER0) & ARMV7_COUNTER_MASK) /* * Per-CPU PMNC: config reg @@ -708,103 +712,76 @@ enum armv7_counters { #define ARMV7_PMNC_MASK 0x3f /* Mask for writable bits */ /* - * Available counters - */ -#define ARMV7_CNT0 0 /* First event counter */ -#define ARMV7_CCNT 31 /* Cycle counter */ - -/* Perf Event to low level counters mapping */ -#define ARMV7_EVENT_CNT_TO_CNTx (ARMV7_COUNTER0 - ARMV7_CNT0) - -/* - * CNTENS: counters enable reg - */ -#define ARMV7_CNTENS_P(idx) (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx)) -#define ARMV7_CNTENS_C (1 << ARMV7_CCNT) - -/* - * CNTENC: counters disable reg - */ -#define ARMV7_CNTENC_P(idx) (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx)) -#define ARMV7_CNTENC_C (1 << ARMV7_CCNT) - -/* - * INTENS: counters overflow interrupt enable reg - */ -#define ARMV7_INTENS_P(idx) (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx)) -#define ARMV7_INTENS_C (1 << ARMV7_CCNT) - -/* - * INTENC: counters overflow interrupt disable reg - */ -#define ARMV7_INTENC_P(idx) (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx)) -#define ARMV7_INTENC_C (1 << ARMV7_CCNT) - -/* - * EVTSEL: Event selection reg + * FLAG: counters overflow flag status reg */ -#define ARMV7_EVTSEL_MASK 0xff /* Mask for writable bits */ +#define ARMV7_FLAG_MASK 0xffffffff /* Mask for writable bits */ +#define ARMV7_OVERFLOWED_MASK ARMV7_FLAG_MASK /* - * SELECT: Counter selection reg + * PMXEVTYPER: Event selection reg */ -#define ARMV7_SELECT_MASK 0x1f /* Mask for writable bits */ +#define ARMV7_EVTYPE_MASK 0xc00000ff /* Mask for writable bits */ +#define ARMV7_EVTYPE_EVENT 0xff /* Mask for EVENT bits */ /* - * FLAG: counters overflow flag status reg + * Event filters for PMUv2 */ -#define ARMV7_FLAG_P(idx) (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx)) -#define ARMV7_FLAG_C (1 << ARMV7_CCNT) -#define ARMV7_FLAG_MASK 0xffffffff /* Mask for writable bits */ -#define ARMV7_OVERFLOWED_MASK ARMV7_FLAG_MASK +#define ARMV7_EXCLUDE_PL1 (1 << 31) +#define ARMV7_EXCLUDE_USER (1 << 30) +#define ARMV7_INCLUDE_HYP (1 << 27) -static inline unsigned long armv7_pmnc_read(void) +static inline u32 armv7_pmnc_read(void) { u32 val; asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r"(val)); return val; } -static inline void armv7_pmnc_write(unsigned long val) +static inline void armv7_pmnc_write(u32 val) { val &= ARMV7_PMNC_MASK; isb(); asm volatile("mcr p15, 0, %0, c9, c12, 0" : : "r"(val)); } -static inline int armv7_pmnc_has_overflowed(unsigned long pmnc) +static inline int armv7_pmnc_has_overflowed(u32 pmnc) { return pmnc & ARMV7_OVERFLOWED_MASK; } -static inline int armv7_pmnc_counter_has_overflowed(unsigned long pmnc, - enum armv7_counters counter) +static inline int armv7_pmnc_counter_valid(int idx) +{ + return idx >= ARMV7_IDX_CYCLE_COUNTER && idx <= ARMV7_IDX_COUNTER_LAST; +} + +static inline int armv7_pmnc_counter_has_overflowed(u32 pmnc, int idx) { int ret = 0; + u32 counter; - if (counter == ARMV7_CYCLE_COUNTER) - ret = pmnc & ARMV7_FLAG_C; - else if ((counter >= ARMV7_COUNTER0) && (counter <= ARMV7_COUNTER_LAST)) - ret = pmnc & ARMV7_FLAG_P(counter); - else + if (!armv7_pmnc_counter_valid(idx)) { pr_err("CPU%u checking wrong counter %d overflow status\n", - smp_processor_id(), counter); + smp_processor_id(), idx); + } else { + counter = ARMV7_IDX_TO_COUNTER(idx); + ret = pmnc & BIT(counter); + } return ret; } -static inline int armv7_pmnc_select_counter(unsigned int idx) +static inline int armv7_pmnc_select_counter(int idx) { - u32 val; + u32 counter; - if ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST)) { - pr_err("CPU%u selecting wrong PMNC counter" - " %d\n", smp_processor_id(), idx); - return -1; + if (!armv7_pmnc_counter_valid(idx)) { + pr_err("CPU%u selecting wrong PMNC counter %d\n", + smp_processor_id(), idx); + return -EINVAL; } - val = (idx - ARMV7_EVENT_CNT_TO_CNTx) & ARMV7_SELECT_MASK; - asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (val)); + counter = ARMV7_IDX_TO_COUNTER(idx); + asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (counter)); isb(); return idx; @@ -812,124 +789,95 @@ static inline int armv7_pmnc_select_counter(unsigned int idx) static inline u32 armv7pmu_read_counter(int idx) { - unsigned long value = 0; + u32 value = 0; - if (idx == ARMV7_CYCLE_COUNTER) - asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (value)); - else if ((idx >= ARMV7_COUNTER0) && (idx <= ARMV7_COUNTER_LAST)) { - if (armv7_pmnc_select_counter(idx) == idx) - asm volatile("mrc p15, 0, %0, c9, c13, 2" - : "=r" (value)); - } else + if (!armv7_pmnc_counter_valid(idx)) pr_err("CPU%u reading wrong counter %d\n", smp_processor_id(), idx); + else if (idx == ARMV7_IDX_CYCLE_COUNTER) + asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (value)); + else if (armv7_pmnc_select_counter(idx) == idx) + asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (value)); return value; } static inline void armv7pmu_write_counter(int idx, u32 value) { - if (idx == ARMV7_CYCLE_COUNTER) - asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (value)); - else if ((idx >= ARMV7_COUNTER0) && (idx <= ARMV7_COUNTER_LAST)) { - if (armv7_pmnc_select_counter(idx) == idx) - asm volatile("mcr p15, 0, %0, c9, c13, 2" - : : "r" (value)); - } else + if (!armv7_pmnc_counter_valid(idx)) pr_err("CPU%u writing wrong counter %d\n", smp_processor_id(), idx); + else if (idx == ARMV7_IDX_CYCLE_COUNTER) + asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (value)); + else if (armv7_pmnc_select_counter(idx) == idx) + asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (value)); } -static inline void armv7_pmnc_write_evtsel(unsigned int idx, u32 val) +static inline void armv7_pmnc_write_evtsel(int idx, u32 val) { if (armv7_pmnc_select_counter(idx) == idx) { - val &= ARMV7_EVTSEL_MASK; + val &= ARMV7_EVTYPE_MASK; asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (val)); } } -static inline u32 armv7_pmnc_enable_counter(unsigned int idx) +static inline int armv7_pmnc_enable_counter(int idx) { - u32 val; + u32 counter; - if ((idx != ARMV7_CYCLE_COUNTER) && - ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) { - pr_err("CPU%u enabling wrong PMNC counter" - " %d\n", smp_processor_id(), idx); - return -1; + if (!armv7_pmnc_counter_valid(idx)) { + pr_err("CPU%u enabling wrong PMNC counter %d\n", + smp_processor_id(), idx); + return -EINVAL; } - if (idx == ARMV7_CYCLE_COUNTER) - val = ARMV7_CNTENS_C; - else - val = ARMV7_CNTENS_P(idx); - - asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (val)); - + counter = ARMV7_IDX_TO_COUNTER(idx); + asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (BIT(counter))); return idx; } -static inline u32 armv7_pmnc_disable_counter(unsigned int idx) +static inline int armv7_pmnc_disable_counter(int idx) { - u32 val; - + u32 counter; - if ((idx != ARMV7_CYCLE_COUNTER) && - ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) { - pr_err("CPU%u disabling wrong PMNC counter" - " %d\n", smp_processor_id(), idx); - return -1; + if (!armv7_pmnc_counter_valid(idx)) { + pr_err("CPU%u disabling wrong PMNC counter %d\n", + smp_processor_id(), idx); + return -EINVAL; } - if (idx == ARMV7_CYCLE_COUNTER) - val = ARMV7_CNTENC_C; - else - val = ARMV7_CNTENC_P(idx); - - asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (val)); - + counter = ARMV7_IDX_TO_COUNTER(idx); + asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (BIT(counter))); return idx; } -static inline u32 armv7_pmnc_enable_intens(unsigned int idx) +static inline int armv7_pmnc_enable_intens(int idx) { - u32 val; + u32 counter; - if ((idx != ARMV7_CYCLE_COUNTER) && - ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) { - pr_err("CPU%u enabling wrong PMNC counter" - " interrupt enable %d\n", smp_processor_id(), idx); - return -1; + if (!armv7_pmnc_counter_valid(idx)) { + pr_err("CPU%u enabling wrong PMNC counter IRQ enable %d\n", + smp_processor_id(), idx); + return -EINVAL; } - if (idx == ARMV7_CYCLE_COUNTER) - val = ARMV7_INTENS_C; - else - val = ARMV7_INTENS_P(idx); - - asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (val)); - + counter = ARMV7_IDX_TO_COUNTER(idx); + asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (BIT(counter))); return idx; } -static inline u32 armv7_pmnc_disable_intens(unsigned int idx) +static inline int armv7_pmnc_disable_intens(int idx) { - u32 val; + u32 counter; - if ((idx != ARMV7_CYCLE_COUNTER) && - ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) { - pr_err("CPU%u disabling wrong PMNC counter" - " interrupt enable %d\n", smp_processor_id(), idx); - return -1; + if (!armv7_pmnc_counter_valid(idx)) { + pr_err("CPU%u disabling wrong PMNC counter IRQ enable %d\n", + smp_processor_id(), idx); + return -EINVAL; } - if (idx == ARMV7_CYCLE_COUNTER) - val = ARMV7_INTENC_C; - else - val = ARMV7_INTENC_P(idx); - - asm volatile("mcr p15, 0, %0, c9, c14, 2" : : "r" (val)); - + counter = ARMV7_IDX_TO_COUNTER(idx); + asm volatile("mcr p15, 0, %0, c9, c14, 2" : : "r" (BIT(counter))); return idx; } @@ -973,14 +921,14 @@ static void armv7_pmnc_dump_regs(void) asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val)); printk(KERN_INFO "CCNT =0x%08x\n", val); - for (cnt = ARMV7_COUNTER0; cnt < ARMV7_COUNTER_LAST; cnt++) { + for (cnt = ARMV7_IDX_COUNTER0; cnt <= ARMV7_IDX_COUNTER_LAST; cnt++) { armv7_pmnc_select_counter(cnt); asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (val)); printk(KERN_INFO "CNT[%d] count =0x%08x\n", - cnt-ARMV7_EVENT_CNT_TO_CNTx, val); + ARMV7_IDX_TO_COUNTER(cnt), val); asm volatile("mrc p15, 0, %0, c9, c13, 1" : "=r" (val)); printk(KERN_INFO "CNT[%d] evtsel=0x%08x\n", - cnt-ARMV7_EVENT_CNT_TO_CNTx, val); + ARMV7_IDX_TO_COUNTER(cnt), val); } } #endif @@ -988,12 +936,13 @@ static void armv7_pmnc_dump_regs(void) static void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx) { unsigned long flags; + struct pmu_hw_events *events = cpu_pmu->get_hw_events(); /* * Enable counter and interrupt, and set the counter to count * the event that we're interested in. */ - raw_spin_lock_irqsave(&pmu_lock, flags); + raw_spin_lock_irqsave(&events->pmu_lock, flags); /* * Disable counter @@ -1002,9 +951,10 @@ static void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx) /* * Set event (if destined for PMNx counters) - * We don't need to set the event if it's a cycle count + * We only need to set the event for the cycle counter if we + * have the ability to perform event filtering. */ - if (idx != ARMV7_CYCLE_COUNTER) + if (armv7pmu.set_event_filter || idx != ARMV7_IDX_CYCLE_COUNTER) armv7_pmnc_write_evtsel(idx, hwc->config_base); /* @@ -1017,17 +967,18 @@ static void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx) */ armv7_pmnc_enable_counter(idx); - raw_spin_unlock_irqrestore(&pmu_lock, flags); + raw_spin_unlock_irqrestore(&events->pmu_lock, flags); } static void armv7pmu_disable_event(struct hw_perf_event *hwc, int idx) { unsigned long flags; + struct pmu_hw_events *events = cpu_pmu->get_hw_events(); /* * Disable counter and interrupt */ - raw_spin_lock_irqsave(&pmu_lock, flags); + raw_spin_lock_irqsave(&events->pmu_lock, flags); /* * Disable counter @@ -1039,14 +990,14 @@ static void armv7pmu_disable_event(struct hw_perf_event *hwc, int idx) */ armv7_pmnc_disable_intens(idx); - raw_spin_unlock_irqrestore(&pmu_lock, flags); + raw_spin_unlock_irqrestore(&events->pmu_lock, flags); } static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev) { - unsigned long pmnc; + u32 pmnc; struct perf_sample_data data; - struct cpu_hw_events *cpuc; + struct pmu_hw_events *cpuc; struct pt_regs *regs; int idx; @@ -1069,13 +1020,10 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev) perf_sample_data_init(&data, 0); cpuc = &__get_cpu_var(cpu_hw_events); - for (idx = 0; idx <= armpmu->num_events; ++idx) { + for (idx = 0; idx < cpu_pmu->num_events; ++idx) { struct perf_event *event = cpuc->events[idx]; struct hw_perf_event *hwc; - if (!test_bit(idx, cpuc->active_mask)) - continue; - /* * We have a single interrupt for all counters. Check that * each counter has overflowed before we process it. @@ -1090,7 +1038,7 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev) continue; if (perf_event_overflow(event, &data, regs)) - armpmu->disable(hwc, idx); + cpu_pmu->disable(hwc, idx); } /* @@ -1108,61 +1056,114 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev) static void armv7pmu_start(void) { unsigned long flags; + struct pmu_hw_events *events = cpu_pmu->get_hw_events(); - raw_spin_lock_irqsave(&pmu_lock, flags); + raw_spin_lock_irqsave(&events->pmu_lock, flags); /* Enable all counters */ armv7_pmnc_write(armv7_pmnc_read() | ARMV7_PMNC_E); - raw_spin_unlock_irqrestore(&pmu_lock, flags); + raw_spin_unlock_irqrestore(&events->pmu_lock, flags); } static void armv7pmu_stop(void) { unsigned long flags; + struct pmu_hw_events *events = cpu_pmu->get_hw_events(); - raw_spin_lock_irqsave(&pmu_lock, flags); + raw_spin_lock_irqsave(&events->pmu_lock, flags); /* Disable all counters */ armv7_pmnc_write(armv7_pmnc_read() & ~ARMV7_PMNC_E); - raw_spin_unlock_irqrestore(&pmu_lock, flags); + raw_spin_unlock_irqrestore(&events->pmu_lock, flags); } -static int armv7pmu_get_event_idx(struct cpu_hw_events *cpuc, +static int armv7pmu_get_event_idx(struct pmu_hw_events *cpuc, struct hw_perf_event *event) { int idx; + unsigned long evtype = event->config_base & ARMV7_EVTYPE_EVENT; /* Always place a cycle counter into the cycle counter. */ - if (event->config_base == ARMV7_PERFCTR_CPU_CYCLES) { - if (test_and_set_bit(ARMV7_CYCLE_COUNTER, cpuc->used_mask)) + if (evtype == ARMV7_PERFCTR_CPU_CYCLES) { + if (test_and_set_bit(ARMV7_IDX_CYCLE_COUNTER, cpuc->used_mask)) return -EAGAIN; - return ARMV7_CYCLE_COUNTER; - } else { - /* - * For anything other than a cycle counter, try and use - * the events counters - */ - for (idx = ARMV7_COUNTER0; idx <= armpmu->num_events; ++idx) { - if (!test_and_set_bit(idx, cpuc->used_mask)) - return idx; - } + return ARMV7_IDX_CYCLE_COUNTER; + } - /* The counters are all in use. */ - return -EAGAIN; + /* + * For anything other than a cycle counter, try and use + * the events counters + */ + for (idx = ARMV7_IDX_COUNTER0; idx < cpu_pmu->num_events; ++idx) { + if (!test_and_set_bit(idx, cpuc->used_mask)) + return idx; } + + /* The counters are all in use. */ + return -EAGAIN; +} + +/* + * Add an event filter to a given event. This will only work for PMUv2 PMUs. + */ +static int armv7pmu_set_event_filter(struct hw_perf_event *event, + struct perf_event_attr *attr) +{ + unsigned long config_base = 0; + + if (attr->exclude_idle) + return -EPERM; + if (attr->exclude_user) + config_base |= ARMV7_EXCLUDE_USER; + if (attr->exclude_kernel) + config_base |= ARMV7_EXCLUDE_PL1; + if (!attr->exclude_hv) + config_base |= ARMV7_INCLUDE_HYP; + + /* + * Install the filter into config_base as this is used to + * construct the event type. + */ + event->config_base = config_base; + + return 0; } static void armv7pmu_reset(void *info) { - u32 idx, nb_cnt = armpmu->num_events; + u32 idx, nb_cnt = cpu_pmu->num_events; /* The counter and interrupt enable registers are unknown at reset. */ - for (idx = 1; idx < nb_cnt; ++idx) + for (idx = ARMV7_IDX_CYCLE_COUNTER; idx < nb_cnt; ++idx) armv7pmu_disable_event(NULL, idx); /* Initialize & Reset PMNC: C and P bits */ armv7_pmnc_write(ARMV7_PMNC_P | ARMV7_PMNC_C); } +static int armv7_a8_map_event(struct perf_event *event) +{ + return map_cpu_event(event, &armv7_a8_perf_map, + &armv7_a8_perf_cache_map, 0xFF); +} + +static int armv7_a9_map_event(struct perf_event *event) +{ + return map_cpu_event(event, &armv7_a9_perf_map, + &armv7_a9_perf_cache_map, 0xFF); +} + +static int armv7_a5_map_event(struct perf_event *event) +{ + return map_cpu_event(event, &armv7_a5_perf_map, + &armv7_a5_perf_cache_map, 0xFF); +} + +static int armv7_a15_map_event(struct perf_event *event) +{ + return map_cpu_event(event, &armv7_a15_perf_map, + &armv7_a15_perf_cache_map, 0xFF); +} + static struct arm_pmu armv7pmu = { .handle_irq = armv7pmu_handle_irq, .enable = armv7pmu_enable_event, @@ -1173,7 +1174,6 @@ static struct arm_pmu armv7pmu = { .start = armv7pmu_start, .stop = armv7pmu_stop, .reset = armv7pmu_reset, - .raw_event_mask = 0xFF, .max_period = (1LLU << 32) - 1, }; @@ -1188,62 +1188,59 @@ static u32 __init armv7_read_num_pmnc_events(void) return nb_cnt + 1; } -static const struct arm_pmu *__init armv7_a8_pmu_init(void) +static struct arm_pmu *__init armv7_a8_pmu_init(void) { armv7pmu.id = ARM_PERF_PMU_ID_CA8; armv7pmu.name = "ARMv7 Cortex-A8"; - armv7pmu.cache_map = &armv7_a8_perf_cache_map; - armv7pmu.event_map = &armv7_a8_perf_map; + armv7pmu.map_event = armv7_a8_map_event; armv7pmu.num_events = armv7_read_num_pmnc_events(); return &armv7pmu; } -static const struct arm_pmu *__init armv7_a9_pmu_init(void) +static struct arm_pmu *__init armv7_a9_pmu_init(void) { armv7pmu.id = ARM_PERF_PMU_ID_CA9; armv7pmu.name = "ARMv7 Cortex-A9"; - armv7pmu.cache_map = &armv7_a9_perf_cache_map; - armv7pmu.event_map = &armv7_a9_perf_map; + armv7pmu.map_event = armv7_a9_map_event; armv7pmu.num_events = armv7_read_num_pmnc_events(); return &armv7pmu; } -static const struct arm_pmu *__init armv7_a5_pmu_init(void) +static struct arm_pmu *__init armv7_a5_pmu_init(void) { armv7pmu.id = ARM_PERF_PMU_ID_CA5; armv7pmu.name = "ARMv7 Cortex-A5"; - armv7pmu.cache_map = &armv7_a5_perf_cache_map; - armv7pmu.event_map = &armv7_a5_perf_map; + armv7pmu.map_event = armv7_a5_map_event; armv7pmu.num_events = armv7_read_num_pmnc_events(); return &armv7pmu; } -static const struct arm_pmu *__init armv7_a15_pmu_init(void) +static struct arm_pmu *__init armv7_a15_pmu_init(void) { armv7pmu.id = ARM_PERF_PMU_ID_CA15; armv7pmu.name = "ARMv7 Cortex-A15"; - armv7pmu.cache_map = &armv7_a15_perf_cache_map; - armv7pmu.event_map = &armv7_a15_perf_map; + armv7pmu.map_event = armv7_a15_map_event; armv7pmu.num_events = armv7_read_num_pmnc_events(); + armv7pmu.set_event_filter = armv7pmu_set_event_filter; return &armv7pmu; } #else -static const struct arm_pmu *__init armv7_a8_pmu_init(void) +static struct arm_pmu *__init armv7_a8_pmu_init(void) { return NULL; } -static const struct arm_pmu *__init armv7_a9_pmu_init(void) +static struct arm_pmu *__init armv7_a9_pmu_init(void) { return NULL; } -static const struct arm_pmu *__init armv7_a5_pmu_init(void) +static struct arm_pmu *__init armv7_a5_pmu_init(void) { return NULL; } -static const struct arm_pmu *__init armv7_a15_pmu_init(void) +static struct arm_pmu *__init armv7_a15_pmu_init(void) { return NULL; } diff --git a/arch/arm/kernel/perf_event_xscale.c b/arch/arm/kernel/perf_event_xscale.c index 3c4397491d080f2425b3a2b28bf3c5306e422a43..e0cca10a8411d51d6a7cf1fadef714213a76de81 100644 --- a/arch/arm/kernel/perf_event_xscale.c +++ b/arch/arm/kernel/perf_event_xscale.c @@ -40,7 +40,7 @@ enum xscale_perf_types { }; enum xscale_counters { - XSCALE_CYCLE_COUNTER = 1, + XSCALE_CYCLE_COUNTER = 0, XSCALE_COUNTER0, XSCALE_COUNTER1, XSCALE_COUNTER2, @@ -222,7 +222,7 @@ xscale1pmu_handle_irq(int irq_num, void *dev) { unsigned long pmnc; struct perf_sample_data data; - struct cpu_hw_events *cpuc; + struct pmu_hw_events *cpuc; struct pt_regs *regs; int idx; @@ -249,13 +249,10 @@ xscale1pmu_handle_irq(int irq_num, void *dev) perf_sample_data_init(&data, 0); cpuc = &__get_cpu_var(cpu_hw_events); - for (idx = 0; idx <= armpmu->num_events; ++idx) { + for (idx = 0; idx < cpu_pmu->num_events; ++idx) { struct perf_event *event = cpuc->events[idx]; struct hw_perf_event *hwc; - if (!test_bit(idx, cpuc->active_mask)) - continue; - if (!xscale1_pmnc_counter_has_overflowed(pmnc, idx)) continue; @@ -266,7 +263,7 @@ xscale1pmu_handle_irq(int irq_num, void *dev) continue; if (perf_event_overflow(event, &data, regs)) - armpmu->disable(hwc, idx); + cpu_pmu->disable(hwc, idx); } irq_work_run(); @@ -284,6 +281,7 @@ static void xscale1pmu_enable_event(struct hw_perf_event *hwc, int idx) { unsigned long val, mask, evt, flags; + struct pmu_hw_events *events = cpu_pmu->get_hw_events(); switch (idx) { case XSCALE_CYCLE_COUNTER: @@ -305,18 +303,19 @@ xscale1pmu_enable_event(struct hw_perf_event *hwc, int idx) return; } - raw_spin_lock_irqsave(&pmu_lock, flags); + raw_spin_lock_irqsave(&events->pmu_lock, flags); val = xscale1pmu_read_pmnc(); val &= ~mask; val |= evt; xscale1pmu_write_pmnc(val); - raw_spin_unlock_irqrestore(&pmu_lock, flags); + raw_spin_unlock_irqrestore(&events->pmu_lock, flags); } static void xscale1pmu_disable_event(struct hw_perf_event *hwc, int idx) { unsigned long val, mask, evt, flags; + struct pmu_hw_events *events = cpu_pmu->get_hw_events(); switch (idx) { case XSCALE_CYCLE_COUNTER: @@ -336,16 +335,16 @@ xscale1pmu_disable_event(struct hw_perf_event *hwc, int idx) return; } - raw_spin_lock_irqsave(&pmu_lock, flags); + raw_spin_lock_irqsave(&events->pmu_lock, flags); val = xscale1pmu_read_pmnc(); val &= ~mask; val |= evt; xscale1pmu_write_pmnc(val); - raw_spin_unlock_irqrestore(&pmu_lock, flags); + raw_spin_unlock_irqrestore(&events->pmu_lock, flags); } static int -xscale1pmu_get_event_idx(struct cpu_hw_events *cpuc, +xscale1pmu_get_event_idx(struct pmu_hw_events *cpuc, struct hw_perf_event *event) { if (XSCALE_PERFCTR_CCNT == event->config_base) { @@ -368,24 +367,26 @@ static void xscale1pmu_start(void) { unsigned long flags, val; + struct pmu_hw_events *events = cpu_pmu->get_hw_events(); - raw_spin_lock_irqsave(&pmu_lock, flags); + raw_spin_lock_irqsave(&events->pmu_lock, flags); val = xscale1pmu_read_pmnc(); val |= XSCALE_PMU_ENABLE; xscale1pmu_write_pmnc(val); - raw_spin_unlock_irqrestore(&pmu_lock, flags); + raw_spin_unlock_irqrestore(&events->pmu_lock, flags); } static void xscale1pmu_stop(void) { unsigned long flags, val; + struct pmu_hw_events *events = cpu_pmu->get_hw_events(); - raw_spin_lock_irqsave(&pmu_lock, flags); + raw_spin_lock_irqsave(&events->pmu_lock, flags); val = xscale1pmu_read_pmnc(); val &= ~XSCALE_PMU_ENABLE; xscale1pmu_write_pmnc(val); - raw_spin_unlock_irqrestore(&pmu_lock, flags); + raw_spin_unlock_irqrestore(&events->pmu_lock, flags); } static inline u32 @@ -424,7 +425,13 @@ xscale1pmu_write_counter(int counter, u32 val) } } -static const struct arm_pmu xscale1pmu = { +static int xscale_map_event(struct perf_event *event) +{ + return map_cpu_event(event, &xscale_perf_map, + &xscale_perf_cache_map, 0xFF); +} + +static struct arm_pmu xscale1pmu = { .id = ARM_PERF_PMU_ID_XSCALE1, .name = "xscale1", .handle_irq = xscale1pmu_handle_irq, @@ -435,14 +442,12 @@ static const struct arm_pmu xscale1pmu = { .get_event_idx = xscale1pmu_get_event_idx, .start = xscale1pmu_start, .stop = xscale1pmu_stop, - .cache_map = &xscale_perf_cache_map, - .event_map = &xscale_perf_map, - .raw_event_mask = 0xFF, + .map_event = xscale_map_event, .num_events = 3, .max_period = (1LLU << 32) - 1, }; -static const struct arm_pmu *__init xscale1pmu_init(void) +static struct arm_pmu *__init xscale1pmu_init(void) { return &xscale1pmu; } @@ -560,7 +565,7 @@ xscale2pmu_handle_irq(int irq_num, void *dev) { unsigned long pmnc, of_flags; struct perf_sample_data data; - struct cpu_hw_events *cpuc; + struct pmu_hw_events *cpuc; struct pt_regs *regs; int idx; @@ -581,13 +586,10 @@ xscale2pmu_handle_irq(int irq_num, void *dev) perf_sample_data_init(&data, 0); cpuc = &__get_cpu_var(cpu_hw_events); - for (idx = 0; idx <= armpmu->num_events; ++idx) { + for (idx = 0; idx < cpu_pmu->num_events; ++idx) { struct perf_event *event = cpuc->events[idx]; struct hw_perf_event *hwc; - if (!test_bit(idx, cpuc->active_mask)) - continue; - if (!xscale2_pmnc_counter_has_overflowed(pmnc, idx)) continue; @@ -598,7 +600,7 @@ xscale2pmu_handle_irq(int irq_num, void *dev) continue; if (perf_event_overflow(event, &data, regs)) - armpmu->disable(hwc, idx); + cpu_pmu->disable(hwc, idx); } irq_work_run(); @@ -616,6 +618,7 @@ static void xscale2pmu_enable_event(struct hw_perf_event *hwc, int idx) { unsigned long flags, ien, evtsel; + struct pmu_hw_events *events = cpu_pmu->get_hw_events(); ien = xscale2pmu_read_int_enable(); evtsel = xscale2pmu_read_event_select(); @@ -649,16 +652,17 @@ xscale2pmu_enable_event(struct hw_perf_event *hwc, int idx) return; } - raw_spin_lock_irqsave(&pmu_lock, flags); + raw_spin_lock_irqsave(&events->pmu_lock, flags); xscale2pmu_write_event_select(evtsel); xscale2pmu_write_int_enable(ien); - raw_spin_unlock_irqrestore(&pmu_lock, flags); + raw_spin_unlock_irqrestore(&events->pmu_lock, flags); } static void xscale2pmu_disable_event(struct hw_perf_event *hwc, int idx) { unsigned long flags, ien, evtsel; + struct pmu_hw_events *events = cpu_pmu->get_hw_events(); ien = xscale2pmu_read_int_enable(); evtsel = xscale2pmu_read_event_select(); @@ -692,14 +696,14 @@ xscale2pmu_disable_event(struct hw_perf_event *hwc, int idx) return; } - raw_spin_lock_irqsave(&pmu_lock, flags); + raw_spin_lock_irqsave(&events->pmu_lock, flags); xscale2pmu_write_event_select(evtsel); xscale2pmu_write_int_enable(ien); - raw_spin_unlock_irqrestore(&pmu_lock, flags); + raw_spin_unlock_irqrestore(&events->pmu_lock, flags); } static int -xscale2pmu_get_event_idx(struct cpu_hw_events *cpuc, +xscale2pmu_get_event_idx(struct pmu_hw_events *cpuc, struct hw_perf_event *event) { int idx = xscale1pmu_get_event_idx(cpuc, event); @@ -718,24 +722,26 @@ static void xscale2pmu_start(void) { unsigned long flags, val; + struct pmu_hw_events *events = cpu_pmu->get_hw_events(); - raw_spin_lock_irqsave(&pmu_lock, flags); + raw_spin_lock_irqsave(&events->pmu_lock, flags); val = xscale2pmu_read_pmnc() & ~XSCALE_PMU_CNT64; val |= XSCALE_PMU_ENABLE; xscale2pmu_write_pmnc(val); - raw_spin_unlock_irqrestore(&pmu_lock, flags); + raw_spin_unlock_irqrestore(&events->pmu_lock, flags); } static void xscale2pmu_stop(void) { unsigned long flags, val; + struct pmu_hw_events *events = cpu_pmu->get_hw_events(); - raw_spin_lock_irqsave(&pmu_lock, flags); + raw_spin_lock_irqsave(&events->pmu_lock, flags); val = xscale2pmu_read_pmnc(); val &= ~XSCALE_PMU_ENABLE; xscale2pmu_write_pmnc(val); - raw_spin_unlock_irqrestore(&pmu_lock, flags); + raw_spin_unlock_irqrestore(&events->pmu_lock, flags); } static inline u32 @@ -786,7 +792,7 @@ xscale2pmu_write_counter(int counter, u32 val) } } -static const struct arm_pmu xscale2pmu = { +static struct arm_pmu xscale2pmu = { .id = ARM_PERF_PMU_ID_XSCALE2, .name = "xscale2", .handle_irq = xscale2pmu_handle_irq, @@ -797,24 +803,22 @@ static const struct arm_pmu xscale2pmu = { .get_event_idx = xscale2pmu_get_event_idx, .start = xscale2pmu_start, .stop = xscale2pmu_stop, - .cache_map = &xscale_perf_cache_map, - .event_map = &xscale_perf_map, - .raw_event_mask = 0xFF, + .map_event = xscale_map_event, .num_events = 5, .max_period = (1LLU << 32) - 1, }; -static const struct arm_pmu *__init xscale2pmu_init(void) +static struct arm_pmu *__init xscale2pmu_init(void) { return &xscale2pmu; } #else -static const struct arm_pmu *__init xscale1pmu_init(void) +static struct arm_pmu *__init xscale1pmu_init(void) { return NULL; } -static const struct arm_pmu *__init xscale2pmu_init(void) +static struct arm_pmu *__init xscale2pmu_init(void) { return NULL; } diff --git a/arch/arm/kernel/pmu.c b/arch/arm/kernel/pmu.c index c53474fe84dfe1851df72fd7428fccf02ea33c4f..2c3407ee857675242c874f49adaf9d26339f79bf 100644 --- a/arch/arm/kernel/pmu.c +++ b/arch/arm/kernel/pmu.c @@ -10,192 +10,26 @@ * */ -#define pr_fmt(fmt) "PMU: " fmt - -#include #include -#include #include #include -#include -#include #include -static volatile long pmu_lock; - -static struct platform_device *pmu_devices[ARM_NUM_PMU_DEVICES]; - -static int __devinit pmu_register(struct platform_device *pdev, - enum arm_pmu_type type) -{ - if (type < 0 || type >= ARM_NUM_PMU_DEVICES) { - pr_warning("received registration request for unknown " - "PMU device type %d\n", type); - return -EINVAL; - } - - if (pmu_devices[type]) { - pr_warning("rejecting duplicate registration of PMU device " - "type %d.", type); - return -ENOSPC; - } - - pr_info("registered new PMU device of type %d\n", type); - pmu_devices[type] = pdev; - return 0; -} - -#define OF_MATCH_PMU(_name, _type) { \ - .compatible = _name, \ - .data = (void *)_type, \ -} - -#define OF_MATCH_CPU(name) OF_MATCH_PMU(name, ARM_PMU_DEVICE_CPU) - -static struct of_device_id armpmu_of_device_ids[] = { - OF_MATCH_CPU("arm,cortex-a9-pmu"), - OF_MATCH_CPU("arm,cortex-a8-pmu"), - OF_MATCH_CPU("arm,arm1136-pmu"), - OF_MATCH_CPU("arm,arm1176-pmu"), - {}, -}; - -#define PLAT_MATCH_PMU(_name, _type) { \ - .name = _name, \ - .driver_data = _type, \ -} - -#define PLAT_MATCH_CPU(_name) PLAT_MATCH_PMU(_name, ARM_PMU_DEVICE_CPU) - -static struct platform_device_id armpmu_plat_device_ids[] = { - PLAT_MATCH_CPU("arm-pmu"), - {}, -}; - -enum arm_pmu_type armpmu_device_type(struct platform_device *pdev) -{ - const struct of_device_id *of_id; - const struct platform_device_id *pdev_id; - - /* provided by of_device_id table */ - if (pdev->dev.of_node) { - of_id = of_match_device(armpmu_of_device_ids, &pdev->dev); - BUG_ON(!of_id); - return (enum arm_pmu_type)of_id->data; - } - - /* Provided by platform_device_id table */ - pdev_id = platform_get_device_id(pdev); - BUG_ON(!pdev_id); - return pdev_id->driver_data; -} - -static int __devinit armpmu_device_probe(struct platform_device *pdev) -{ - return pmu_register(pdev, armpmu_device_type(pdev)); -} - -static struct platform_driver armpmu_driver = { - .driver = { - .name = "arm-pmu", - .of_match_table = armpmu_of_device_ids, - }, - .probe = armpmu_device_probe, - .id_table = armpmu_plat_device_ids, -}; - -static int __init register_pmu_driver(void) -{ - return platform_driver_register(&armpmu_driver); -} -device_initcall(register_pmu_driver); +/* + * PMU locking to ensure mutual exclusion between different subsystems. + */ +static unsigned long pmu_lock[BITS_TO_LONGS(ARM_NUM_PMU_DEVICES)]; -struct platform_device * +int reserve_pmu(enum arm_pmu_type type) { - struct platform_device *pdev; - - if (test_and_set_bit_lock(type, &pmu_lock)) { - pdev = ERR_PTR(-EBUSY); - } else if (pmu_devices[type] == NULL) { - clear_bit_unlock(type, &pmu_lock); - pdev = ERR_PTR(-ENODEV); - } else { - pdev = pmu_devices[type]; - } - - return pdev; + return test_and_set_bit_lock(type, pmu_lock) ? -EBUSY : 0; } EXPORT_SYMBOL_GPL(reserve_pmu); -int +void release_pmu(enum arm_pmu_type type) { - if (WARN_ON(!pmu_devices[type])) - return -EINVAL; - clear_bit_unlock(type, &pmu_lock); - return 0; -} -EXPORT_SYMBOL_GPL(release_pmu); - -static int -set_irq_affinity(int irq, - unsigned int cpu) -{ -#ifdef CONFIG_SMP - int err = irq_set_affinity(irq, cpumask_of(cpu)); - if (err) - pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n", - irq, cpu); - return err; -#else - return -EINVAL; -#endif -} - -static int -init_cpu_pmu(void) -{ - int i, irqs, err = 0; - struct platform_device *pdev = pmu_devices[ARM_PMU_DEVICE_CPU]; - - if (!pdev) - return -ENODEV; - - irqs = pdev->num_resources; - - /* - * If we have a single PMU interrupt that we can't shift, assume that - * we're running on a uniprocessor machine and continue. - */ - if (irqs == 1 && !irq_can_set_affinity(platform_get_irq(pdev, 0))) - return 0; - - for (i = 0; i < irqs; ++i) { - err = set_irq_affinity(platform_get_irq(pdev, i), i); - if (err) - break; - } - - return err; -} - -int -init_pmu(enum arm_pmu_type type) -{ - int err = 0; - - switch (type) { - case ARM_PMU_DEVICE_CPU: - err = init_cpu_pmu(); - break; - default: - pr_warning("attempt to initialise PMU of unknown " - "type %d\n", type); - err = -EINVAL; - } - - return err; + clear_bit_unlock(type, pmu_lock); } -EXPORT_SYMBOL_GPL(init_pmu); diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 1a347f481e5e7a5c022b7795c6b9542cb77d529e..fd0814076ff66081c46e2ae34bcd42be5ba62c38 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -319,7 +319,7 @@ void show_regs(struct pt_regs * regs) printk("\n"); printk("Pid: %d, comm: %20s\n", task_pid_nr(current), current->comm); __show_regs(regs); - __backtrace(); + dump_stack(); } ATOMIC_NOTIFIER_HEAD(thread_notify_head); diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index e514c76043b4d2f5af4638f44b889bb2737dc5ad..bda0a218f4a55971a0080d198f42ab2aee8f37cb 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include @@ -42,6 +44,7 @@ #include #include #include +#include #include #include @@ -115,6 +118,13 @@ struct outer_cache_fns outer_cache __read_mostly; EXPORT_SYMBOL(outer_cache); #endif +/* + * Cached cpu_architecture() result for use by assembler code. + * C code should use the cpu_architecture() function instead of accessing this + * variable directly. + */ +int __cpu_architecture __read_mostly = CPU_ARCH_UNKNOWN; + struct stack { u32 irq[3]; u32 abt[3]; @@ -210,7 +220,7 @@ static const char *proc_arch[] = { "?(17)", }; -int cpu_architecture(void) +static int __get_cpu_architecture(void) { int cpu_arch; @@ -243,11 +253,22 @@ int cpu_architecture(void) return cpu_arch; } +int __pure cpu_architecture(void) +{ + BUG_ON(__cpu_architecture == CPU_ARCH_UNKNOWN); + + return __cpu_architecture; +} + static int cpu_has_aliasing_icache(unsigned int arch) { int aliasing_icache; unsigned int id_reg, num_sets, line_size; + /* PIPT caches never alias. */ + if (icache_is_pipt()) + return 0; + /* arch specifies the register format */ switch (arch) { case CPU_ARCH_ARMv7: @@ -282,8 +303,14 @@ static void __init cacheid_init(void) /* ARMv7 register format */ arch = CPU_ARCH_ARMv7; cacheid = CACHEID_VIPT_NONALIASING; - if ((cachetype & (3 << 14)) == 1 << 14) + switch (cachetype & (3 << 14)) { + case (1 << 14): cacheid |= CACHEID_ASID_TAGGED; + break; + case (3 << 14): + cacheid |= CACHEID_PIPT; + break; + } } else { arch = CPU_ARCH_ARMv6; if (cachetype & (1 << 23)) @@ -300,10 +327,11 @@ static void __init cacheid_init(void) printk("CPU: %s data cache, %s instruction cache\n", cache_is_vivt() ? "VIVT" : cache_is_vipt_aliasing() ? "VIPT aliasing" : - cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown", + cache_is_vipt_nonaliasing() ? "PIPT / VIPT nonaliasing" : "unknown", cache_is_vivt() ? "VIVT" : icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" : icache_is_vipt_aliasing() ? "VIPT aliasing" : + icache_is_pipt() ? "PIPT" : cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown"); } @@ -414,6 +442,7 @@ static void __init setup_processor(void) } cpu_name = list->cpu_name; + __cpu_architecture = __get_cpu_architecture(); #ifdef MULTI_CPU processor = *list->proc; @@ -820,25 +849,8 @@ static struct machine_desc * __init setup_machine_tags(unsigned int nr) if (__atags_pointer) tags = phys_to_virt(__atags_pointer); - else if (mdesc->boot_params) { -#ifdef CONFIG_MMU - /* - * We still are executing with a minimal MMU mapping created - * with the presumption that the machine default for this - * is located in the first MB of RAM. Anything else will - * fault and silently hang the kernel at this point. - */ - if (mdesc->boot_params < PHYS_OFFSET || - mdesc->boot_params >= PHYS_OFFSET + SZ_1M) { - printk(KERN_WARNING - "Default boot params at physical 0x%08lx out of reach\n", - mdesc->boot_params); - } else -#endif - { - tags = phys_to_virt(mdesc->boot_params); - } - } + else if (mdesc->atag_offset) + tags = (void *)(PAGE_OFFSET + mdesc->atag_offset); #if defined(CONFIG_DEPRECATED_PARAM_STRUCT) /* @@ -861,7 +873,7 @@ static struct machine_desc * __init setup_machine_tags(unsigned int nr) } if (mdesc->fixup) - mdesc->fixup(mdesc, tags, &from, &meminfo); + mdesc->fixup(tags, &from, &meminfo); if (tags->hdr.tag == ATAG_CORE) { if (meminfo.nr_banks != 0) diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S index dc902f2c68457b0f3277b8112a7a1e867106cde8..020e99c845e722c2928b1fd9816b23e85fbc9d5a 100644 --- a/arch/arm/kernel/sleep.S +++ b/arch/arm/kernel/sleep.S @@ -8,92 +8,61 @@ .text /* - * Save CPU state for a suspend - * r1 = v:p offset - * r2 = suspend function arg0 - * r3 = suspend function + * Save CPU state for a suspend. This saves the CPU general purpose + * registers, and allocates space on the kernel stack to save the CPU + * specific registers and some other data for resume. + * r0 = suspend function arg0 + * r1 = suspend function */ ENTRY(__cpu_suspend) stmfd sp!, {r4 - r11, lr} #ifdef MULTI_CPU ldr r10, =processor - ldr r5, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state - ldr ip, [r10, #CPU_DO_RESUME] @ virtual resume function + ldr r4, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state #else - ldr r5, =cpu_suspend_size - ldr ip, =cpu_do_resume + ldr r4, =cpu_suspend_size #endif - mov r6, sp @ current virtual SP - sub sp, sp, r5 @ allocate CPU state on stack - mov r0, sp @ save pointer to CPU save block - add ip, ip, r1 @ convert resume fn to phys - stmfd sp!, {r1, r6, ip} @ save v:p, virt SP, phys resume fn - ldr r5, =sleep_save_sp - add r6, sp, r1 @ convert SP to phys - stmfd sp!, {r2, r3} @ save suspend func arg and pointer + mov r5, sp @ current virtual SP + add r4, r4, #12 @ Space for pgd, virt sp, phys resume fn + sub sp, sp, r4 @ allocate CPU state on stack + stmfd sp!, {r0, r1} @ save suspend func arg and pointer + add r0, sp, #8 @ save pointer to save block + mov r1, r4 @ size of save block + mov r2, r5 @ virtual SP + ldr r3, =sleep_save_sp #ifdef CONFIG_SMP ALT_SMP(mrc p15, 0, lr, c0, c0, 5) ALT_UP(mov lr, #0) and lr, lr, #15 - str r6, [r5, lr, lsl #2] @ save phys SP -#else - str r6, [r5] @ save phys SP -#endif -#ifdef MULTI_CPU - mov lr, pc - ldr pc, [r10, #CPU_DO_SUSPEND] @ save CPU state -#else - bl cpu_do_suspend -#endif - - @ flush data cache -#ifdef MULTI_CACHE - ldr r10, =cpu_cache - mov lr, pc - ldr pc, [r10, #CACHE_FLUSH_KERN_ALL] -#else - bl __cpuc_flush_kern_all + add r3, r3, lr, lsl #2 #endif + bl __cpu_suspend_save adr lr, BSYM(cpu_suspend_abort) ldmfd sp!, {r0, pc} @ call suspend fn ENDPROC(__cpu_suspend) .ltorg cpu_suspend_abort: - ldmia sp!, {r1 - r3} @ pop v:p, virt SP, phys resume fn + ldmia sp!, {r1 - r3} @ pop phys pgd, virt SP, phys resume fn + teq r0, #0 + moveq r0, #1 @ force non-zero value mov sp, r2 ldmfd sp!, {r4 - r11, pc} ENDPROC(cpu_suspend_abort) /* * r0 = control register value - * r1 = v:p offset (preserved by cpu_do_resume) - * r2 = phys page table base - * r3 = L1 section flags */ + .align 5 ENTRY(cpu_resume_mmu) - adr r4, cpu_resume_turn_mmu_on - mov r4, r4, lsr #20 - orr r3, r3, r4, lsl #20 - ldr r5, [r2, r4, lsl #2] @ save old mapping - str r3, [r2, r4, lsl #2] @ setup 1:1 mapping for mmu code - sub r2, r2, r1 ldr r3, =cpu_resume_after_mmu - bic r1, r0, #CR_C @ ensure D-cache is disabled - b cpu_resume_turn_mmu_on -ENDPROC(cpu_resume_mmu) - .ltorg - .align 5 -cpu_resume_turn_mmu_on: - mcr p15, 0, r1, c1, c0, 0 @ turn on MMU, I-cache, etc - mrc p15, 0, r1, c0, c0, 0 @ read id reg - mov r1, r1 - mov r1, r1 + mcr p15, 0, r0, c1, c0, 0 @ turn on MMU, I-cache, etc + mrc p15, 0, r0, c0, c0, 0 @ read id reg + mov r0, r0 + mov r0, r0 mov pc, r3 @ jump to virtual address -ENDPROC(cpu_resume_turn_mmu_on) +ENDPROC(cpu_resume_mmu) cpu_resume_after_mmu: - str r5, [r2, r4, lsl #2] @ restore old mapping - mcr p15, 0, r0, c1, c0, 0 @ turn on D-cache bl cpu_init @ restore the und/abt/irq banked regs mov r0, #0 @ return zero on success ldmfd sp!, {r4 - r11, pc} @@ -119,7 +88,7 @@ ENTRY(cpu_resume) ldr r0, sleep_save_sp @ stack phys addr #endif setmode PSR_I_BIT | PSR_F_BIT | SVC_MODE, r1 @ set SVC, irqs off - @ load v:p, stack, resume fn + @ load phys pgd, stack, resume fn ARM( ldmia r0!, {r1, sp, pc} ) THUMB( ldmia r0!, {r1, r2, r3} ) THUMB( mov sp, r2 ) diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index d88ff0230e826f8ea15a60560668dcf81ef80373..ef5640b9e218fae4cd3b32cdf1e6482c2ea0cdbf 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -31,6 +30,8 @@ #include #include #include +#include +#include #include #include #include @@ -39,6 +40,7 @@ #include #include #include +#include /* * as from 2.5, kernels no longer have an init_tasks structure @@ -259,6 +261,20 @@ void __ref cpu_die(void) } #endif /* CONFIG_HOTPLUG_CPU */ +int __cpu_logical_map[NR_CPUS]; + +void __init smp_setup_processor_id(void) +{ + int i; + u32 cpu = is_smp() ? read_cpuid_mpidr() & 0xff : 0; + + cpu_logical_map(0) = cpu; + for (i = 1; i < NR_CPUS; ++i) + cpu_logical_map(i) = i == cpu ? 0 : i; + + printk(KERN_INFO "Booting Linux on physical CPU %d\n", cpu); +} + /* * Called by both boot and secondaries to move global data into * per-processor storage. @@ -268,6 +284,8 @@ static void __cpuinit smp_store_cpu_info(unsigned int cpuid) struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid); cpu_info->loops_per_jiffy = loops_per_jiffy; + + store_cpu_topology(cpuid); } /* @@ -301,17 +319,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void) */ platform_secondary_init(cpu); - /* - * Enable local interrupts. - */ notify_cpu_starting(cpu); - local_irq_enable(); - local_fiq_enable(); - - /* - * Setup the percpu timer for this CPU. - */ - percpu_timer_setup(); calibrate_delay(); @@ -323,9 +331,22 @@ asmlinkage void __cpuinit secondary_start_kernel(void) * before we continue. */ set_cpu_online(cpu, true); + + /* + * Setup the percpu timer for this CPU. + */ + percpu_timer_setup(); + while (!cpu_active(cpu)) cpu_relax(); + /* + * cpu_active bit is set, so it's safe to enalbe interrupts + * now. + */ + local_irq_enable(); + local_fiq_enable(); + /* * OK, it's off to the idle thread for us */ @@ -358,6 +379,8 @@ void __init smp_prepare_cpus(unsigned int max_cpus) { unsigned int ncores = num_possible_cpus(); + init_cpu_topology(); + smp_store_cpu_info(smp_processor_id()); /* @@ -437,10 +460,6 @@ u64 smp_irq_stat_cpu(unsigned int cpu) for (i = 0; i < NR_IPI; i++) sum += __get_irq_stat(cpu, ipi_irqs[i]); -#ifdef CONFIG_LOCAL_TIMERS - sum += __get_irq_stat(cpu, local_timer_irqs); -#endif - return sum; } @@ -457,33 +476,6 @@ static void ipi_timer(void) irq_exit(); } -#ifdef CONFIG_LOCAL_TIMERS -asmlinkage void __exception_irq_entry do_local_timer(struct pt_regs *regs) -{ - struct pt_regs *old_regs = set_irq_regs(regs); - int cpu = smp_processor_id(); - - if (local_timer_ack()) { - __inc_irq_stat(cpu, local_timer_irqs); - ipi_timer(); - } - - set_irq_regs(old_regs); -} - -void show_local_irqs(struct seq_file *p, int prec) -{ - unsigned int cpu; - - seq_printf(p, "%*s: ", prec, "LOC"); - - for_each_present_cpu(cpu) - seq_printf(p, "%10u ", __get_irq_stat(cpu, local_timer_irqs)); - - seq_printf(p, " Local timer interrupts\n"); -} -#endif - #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST static void smp_timer_broadcast(const struct cpumask *mask) { @@ -534,11 +526,11 @@ static void percpu_timer_stop(void) unsigned int cpu = smp_processor_id(); struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu); - evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); + local_timer_stop(evt); } #endif -static DEFINE_SPINLOCK(stop_lock); +static DEFINE_RAW_SPINLOCK(stop_lock); /* * ipi_cpu_stop - handle IPI from smp_send_stop() @@ -547,10 +539,10 @@ static void ipi_cpu_stop(unsigned int cpu) { if (system_state == SYSTEM_BOOTING || system_state == SYSTEM_RUNNING) { - spin_lock(&stop_lock); + raw_spin_lock(&stop_lock); printk(KERN_CRIT "CPU%u: stopping\n", cpu); dump_stack(); - spin_unlock(&stop_lock); + raw_spin_unlock(&stop_lock); } set_cpu_online(cpu, false); @@ -566,6 +558,11 @@ static void ipi_cpu_stop(unsigned int cpu) * Main handler for inter-processor interrupts */ asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs) +{ + handle_IPI(ipinr, regs); +} + +void handle_IPI(int ipinr, struct pt_regs *regs) { unsigned int cpu = smp_processor_id(); struct pt_regs *old_regs = set_irq_regs(regs); diff --git a/arch/arm/kernel/smp_scu.c b/arch/arm/kernel/smp_scu.c index 7fcddb75c8777d0c154f0f6b5411e67797011463..8f5dd7963356e9cef5116d067e53b75fb5f61636 100644 --- a/arch/arm/kernel/smp_scu.c +++ b/arch/arm/kernel/smp_scu.c @@ -34,7 +34,7 @@ unsigned int __init scu_get_core_count(void __iomem *scu_base) /* * Enable the SCU */ -void __init scu_enable(void __iomem *scu_base) +void scu_enable(void __iomem *scu_base) { u32 scu_ctrl; diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index 01c186222f3b9d132c670bdba6721a7b3b8f50ce..a8a6682d6b52f38ce464d8f500f91c416c101ee3 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -19,6 +19,7 @@ #include #include +#include #include /* set up by the platform code */ @@ -26,6 +27,8 @@ void __iomem *twd_base; static unsigned long twd_timer_rate; +static struct clock_event_device __percpu **twd_evt; + static void twd_set_mode(enum clock_event_mode mode, struct clock_event_device *clk) { @@ -80,6 +83,12 @@ int twd_timer_ack(void) return 0; } +void twd_timer_stop(struct clock_event_device *clk) +{ + twd_set_mode(CLOCK_EVT_MODE_UNUSED, clk); + disable_percpu_irq(clk->irq); +} + static void __cpuinit twd_calibrate_rate(void) { unsigned long count; @@ -119,11 +128,43 @@ static void __cpuinit twd_calibrate_rate(void) } } +static irqreturn_t twd_handler(int irq, void *dev_id) +{ + struct clock_event_device *evt = *(struct clock_event_device **)dev_id; + + if (twd_timer_ack()) { + evt->event_handler(evt); + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + /* * Setup the local clock events for a CPU. */ void __cpuinit twd_timer_setup(struct clock_event_device *clk) { + struct clock_event_device **this_cpu_clk; + + if (!twd_evt) { + int err; + + twd_evt = alloc_percpu(struct clock_event_device *); + if (!twd_evt) { + pr_err("twd: can't allocate memory\n"); + return; + } + + err = request_percpu_irq(clk->irq, twd_handler, + "twd", twd_evt); + if (err) { + pr_err("twd: can't register interrupt %d (%d)\n", + clk->irq, err); + return; + } + } + twd_calibrate_rate(); clk->name = "local_timer"; @@ -137,8 +178,10 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk) clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk); clk->min_delta_ns = clockevent_delta2ns(0xf, clk); + this_cpu_clk = __this_cpu_ptr(twd_evt); + *this_cpu_clk = clk; + clockevents_register_device(clk); - /* Make sure our local interrupt controller has this enabled */ - gic_enable_ppi(clk->irq); + enable_percpu_irq(clk->irq, 0); } diff --git a/arch/arm/kernel/suspend.c b/arch/arm/kernel/suspend.c new file mode 100644 index 0000000000000000000000000000000000000000..93a22d282c167c1ad9753c81277c8948d153e933 --- /dev/null +++ b/arch/arm/kernel/suspend.c @@ -0,0 +1,72 @@ +#include + +#include +#include +#include +#include +#include + +static pgd_t *suspend_pgd; + +extern int __cpu_suspend(unsigned long, int (*)(unsigned long)); +extern void cpu_resume_mmu(void); + +/* + * This is called by __cpu_suspend() to save the state, and do whatever + * flushing is required to ensure that when the CPU goes to sleep we have + * the necessary data available when the caches are not searched. + */ +void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr) +{ + *save_ptr = virt_to_phys(ptr); + + /* This must correspond to the LDM in cpu_resume() assembly */ + *ptr++ = virt_to_phys(suspend_pgd); + *ptr++ = sp; + *ptr++ = virt_to_phys(cpu_do_resume); + + cpu_do_suspend(ptr); + + flush_cache_all(); + outer_clean_range(*save_ptr, *save_ptr + ptrsz); + outer_clean_range(virt_to_phys(save_ptr), + virt_to_phys(save_ptr) + sizeof(*save_ptr)); +} + +/* + * Hide the first two arguments to __cpu_suspend - these are an implementation + * detail which platform code shouldn't have to know about. + */ +int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) +{ + struct mm_struct *mm = current->active_mm; + int ret; + + if (!suspend_pgd) + return -EINVAL; + + /* + * Provide a temporary page table with an identity mapping for + * the MMU-enable code, required for resuming. On successful + * resume (indicated by a zero return code), we need to switch + * back to the correct page tables. + */ + ret = __cpu_suspend(arg, fn); + if (ret == 0) { + cpu_switch_mm(mm->pgd, mm); + local_flush_tlb_all(); + } + + return ret; +} + +static int __init cpu_suspend_init(void) +{ + suspend_pgd = pgd_alloc(&init_mm); + if (suspend_pgd) { + unsigned long addr = virt_to_phys(cpu_resume_mmu); + identity_mapping_add(suspend_pgd, addr, addr + SECTION_SIZE); + } + return suspend_pgd ? 0 : -ENOMEM; +} +core_initcall(cpu_suspend_init); diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index cb634c3e28e95c6aa6f21ece37341c0e42c9d75b..5a54b95d6bd29ddc2c200b0943c4c0e37389abe8 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c @@ -39,13 +39,11 @@ */ static struct sys_timer *system_timer; -#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) +#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || \ + defined(CONFIG_NVRAM) || defined(CONFIG_NVRAM_MODULE) /* this needs a better home */ DEFINE_SPINLOCK(rtc_lock); - -#ifdef CONFIG_RTC_DRV_CMOS_MODULE EXPORT_SYMBOL(rtc_lock); -#endif #endif /* pc-style 'CMOS' RTC support */ /* change this if you have some constant time drift */ diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c new file mode 100644 index 0000000000000000000000000000000000000000..1040c00405d0f362916c77030249fff754eda5e8 --- /dev/null +++ b/arch/arm/kernel/topology.c @@ -0,0 +1,148 @@ +/* + * arch/arm/kernel/topology.c + * + * Copyright (C) 2011 Linaro Limited. + * Written by: Vincent Guittot + * + * based on arch/sh/kernel/topology.c + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define MPIDR_SMP_BITMASK (0x3 << 30) +#define MPIDR_SMP_VALUE (0x2 << 30) + +#define MPIDR_MT_BITMASK (0x1 << 24) + +/* + * These masks reflect the current use of the affinity levels. + * The affinity level can be up to 16 bits according to ARM ARM + */ + +#define MPIDR_LEVEL0_MASK 0x3 +#define MPIDR_LEVEL0_SHIFT 0 + +#define MPIDR_LEVEL1_MASK 0xF +#define MPIDR_LEVEL1_SHIFT 8 + +#define MPIDR_LEVEL2_MASK 0xFF +#define MPIDR_LEVEL2_SHIFT 16 + +struct cputopo_arm cpu_topology[NR_CPUS]; + +const struct cpumask *cpu_coregroup_mask(unsigned int cpu) +{ + return &cpu_topology[cpu].core_sibling; +} + +/* + * store_cpu_topology is called at boot when only one cpu is running + * and with the mutex cpu_hotplug.lock locked, when several cpus have booted, + * which prevents simultaneous write access to cpu_topology array + */ +void store_cpu_topology(unsigned int cpuid) +{ + struct cputopo_arm *cpuid_topo = &cpu_topology[cpuid]; + unsigned int mpidr; + unsigned int cpu; + + /* If the cpu topology has been already set, just return */ + if (cpuid_topo->core_id != -1) + return; + + mpidr = read_cpuid_mpidr(); + + /* create cpu topology mapping */ + if ((mpidr & MPIDR_SMP_BITMASK) == MPIDR_SMP_VALUE) { + /* + * This is a multiprocessor system + * multiprocessor format & multiprocessor mode field are set + */ + + if (mpidr & MPIDR_MT_BITMASK) { + /* core performance interdependency */ + cpuid_topo->thread_id = (mpidr >> MPIDR_LEVEL0_SHIFT) + & MPIDR_LEVEL0_MASK; + cpuid_topo->core_id = (mpidr >> MPIDR_LEVEL1_SHIFT) + & MPIDR_LEVEL1_MASK; + cpuid_topo->socket_id = (mpidr >> MPIDR_LEVEL2_SHIFT) + & MPIDR_LEVEL2_MASK; + } else { + /* largely independent cores */ + cpuid_topo->thread_id = -1; + cpuid_topo->core_id = (mpidr >> MPIDR_LEVEL0_SHIFT) + & MPIDR_LEVEL0_MASK; + cpuid_topo->socket_id = (mpidr >> MPIDR_LEVEL1_SHIFT) + & MPIDR_LEVEL1_MASK; + } + } else { + /* + * This is an uniprocessor system + * we are in multiprocessor format but uniprocessor system + * or in the old uniprocessor format + */ + cpuid_topo->thread_id = -1; + cpuid_topo->core_id = 0; + cpuid_topo->socket_id = -1; + } + + /* update core and thread sibling masks */ + for_each_possible_cpu(cpu) { + struct cputopo_arm *cpu_topo = &cpu_topology[cpu]; + + if (cpuid_topo->socket_id == cpu_topo->socket_id) { + cpumask_set_cpu(cpuid, &cpu_topo->core_sibling); + if (cpu != cpuid) + cpumask_set_cpu(cpu, + &cpuid_topo->core_sibling); + + if (cpuid_topo->core_id == cpu_topo->core_id) { + cpumask_set_cpu(cpuid, + &cpu_topo->thread_sibling); + if (cpu != cpuid) + cpumask_set_cpu(cpu, + &cpuid_topo->thread_sibling); + } + } + } + smp_wmb(); + + printk(KERN_INFO "CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n", + cpuid, cpu_topology[cpuid].thread_id, + cpu_topology[cpuid].core_id, + cpu_topology[cpuid].socket_id, mpidr); +} + +/* + * init_cpu_topology is called at boot when only one cpu is running + * which prevent simultaneous write access to cpu_topology array + */ +void init_cpu_topology(void) +{ + unsigned int cpu; + + /* init core mask */ + for_each_possible_cpu(cpu) { + struct cputopo_arm *cpu_topo = &(cpu_topology[cpu]); + + cpu_topo->thread_id = -1; + cpu_topo->core_id = -1; + cpu_topo->socket_id = -1; + cpumask_clear(&cpu_topo->core_sibling); + cpumask_clear(&cpu_topo->thread_sibling); + } + smp_wmb(); +} diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index bc9f9da782cb85ff3eb0171b9c0d5b8630397c90..99a57270250936ae69e02abd57b27b8a1c3dd022 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -21,12 +21,14 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -255,7 +257,7 @@ static int __die(const char *str, int err, struct thread_info *thread, struct pt return ret; } -static DEFINE_SPINLOCK(die_lock); +static DEFINE_RAW_SPINLOCK(die_lock); /* * This function is protected against re-entrancy. @@ -267,9 +269,11 @@ void die(const char *str, struct pt_regs *regs, int err) oops_enter(); - spin_lock_irq(&die_lock); + raw_spin_lock_irq(&die_lock); console_verbose(); bust_spinlocks(1); + if (!user_mode(regs)) + report_bug(regs->ARM_pc, regs); ret = __die(str, err, thread, regs); if (regs && kexec_should_crash(thread->task)) @@ -277,7 +281,7 @@ void die(const char *str, struct pt_regs *regs, int err) bust_spinlocks(0); add_taint(TAINT_DIE); - spin_unlock_irq(&die_lock); + raw_spin_unlock_irq(&die_lock); oops_exit(); if (in_interrupt()) @@ -301,25 +305,43 @@ void arm_notify_die(const char *str, struct pt_regs *regs, } } +#ifdef CONFIG_GENERIC_BUG + +int is_valid_bugaddr(unsigned long pc) +{ +#ifdef CONFIG_THUMB2_KERNEL + unsigned short bkpt; +#else + unsigned long bkpt; +#endif + + if (probe_kernel_address((unsigned *)pc, bkpt)) + return 0; + + return bkpt == BUG_INSTR_VALUE; +} + +#endif + static LIST_HEAD(undef_hook); -static DEFINE_SPINLOCK(undef_lock); +static DEFINE_RAW_SPINLOCK(undef_lock); void register_undef_hook(struct undef_hook *hook) { unsigned long flags; - spin_lock_irqsave(&undef_lock, flags); + raw_spin_lock_irqsave(&undef_lock, flags); list_add(&hook->node, &undef_hook); - spin_unlock_irqrestore(&undef_lock, flags); + raw_spin_unlock_irqrestore(&undef_lock, flags); } void unregister_undef_hook(struct undef_hook *hook) { unsigned long flags; - spin_lock_irqsave(&undef_lock, flags); + raw_spin_lock_irqsave(&undef_lock, flags); list_del(&hook->node); - spin_unlock_irqrestore(&undef_lock, flags); + raw_spin_unlock_irqrestore(&undef_lock, flags); } static int call_undef_hook(struct pt_regs *regs, unsigned int instr) @@ -328,12 +350,12 @@ static int call_undef_hook(struct pt_regs *regs, unsigned int instr) unsigned long flags; int (*fn)(struct pt_regs *regs, unsigned int instr) = NULL; - spin_lock_irqsave(&undef_lock, flags); + raw_spin_lock_irqsave(&undef_lock, flags); list_for_each_entry(hook, &undef_hook, node) if ((instr & hook->instr_mask) == hook->instr_val && (regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val) fn = hook->fn; - spin_unlock_irqrestore(&undef_lock, flags); + raw_spin_unlock_irqrestore(&undef_lock, flags); return fn ? fn(regs, instr) : 1; } @@ -706,16 +728,6 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs) arm_notify_die("unknown data abort code", regs, &info, instr, 0); } -void __attribute__((noreturn)) __bug(const char *file, int line) -{ - printk(KERN_CRIT"kernel BUG at %s:%d!\n", file, line); - *(int *)0 = 0; - - /* Avoid "noreturn function does return" */ - for (;;); -} -EXPORT_SYMBOL(__bug); - void __readwrite_bug(const char *fn) { printk("%s called, but not implemented\n", fn); diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 4e66f62b8d41f7321b7dcdc58ec9bd8730afc775..20b3041e0860f7c743f4e453a38c9ce738a10e75 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -21,7 +21,8 @@ #define ARM_CPU_KEEP(x) #endif -#if defined(CONFIG_SMP_ON_UP) && !defined(CONFIG_DEBUG_SPINLOCK) +#if (defined(CONFIG_SMP_ON_UP) && !defined(CONFIG_DEBUG_SPINLOCK)) || \ + defined(CONFIG_GENERIC_BUG) #define ARM_EXIT_KEEP(x) x #define ARM_EXIT_DISCARD(x) #else diff --git a/arch/arm/lib/backtrace.S b/arch/arm/lib/backtrace.S index a673297b0cf14c39acbbfa27dd57a034e7b02410..cd07b5814c2304f0908342b04291af09388790b7 100644 --- a/arch/arm/lib/backtrace.S +++ b/arch/arm/lib/backtrace.S @@ -22,15 +22,10 @@ #define mask r7 #define offset r8 -ENTRY(__backtrace) - mov r1, #0x10 - mov r0, fp - ENTRY(c_backtrace) #if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK) mov pc, lr -ENDPROC(__backtrace) ENDPROC(c_backtrace) #else stmfd sp!, {r4 - r8, lr} @ Save an extra register so we have a location... @@ -107,7 +102,6 @@ for_each_frame: tst frame, mask @ Check for address exceptions mov r1, frame bl printk no_frame: ldmfd sp!, {r4 - r8, pc} -ENDPROC(__backtrace) ENDPROC(c_backtrace) .pushsection __ex_table,"a" diff --git a/arch/arm/lib/div64.S b/arch/arm/lib/div64.S index faa7748142da20a00f829863484904d52124f3af..e55c4842c290fa6267e9998eb9dc4bd28f8cfcef 100644 --- a/arch/arm/lib/div64.S +++ b/arch/arm/lib/div64.S @@ -13,6 +13,7 @@ */ #include +#include #ifdef __ARMEB__ #define xh r0 @@ -44,6 +45,7 @@ */ ENTRY(__do_div64) +UNWIND(.fnstart) @ Test for easy paths first. subs ip, r4, #1 @@ -189,7 +191,12 @@ ENTRY(__do_div64) moveq yh, xh moveq xh, #0 moveq pc, lr +UNWIND(.fnend) +UNWIND(.fnstart) +UNWIND(.pad #4) +UNWIND(.save {lr}) +Ldiv0_64: @ Division by 0: str lr, [sp, #-8]! bl __div0 @@ -200,4 +207,5 @@ ENTRY(__do_div64) mov xh, #0 ldr pc, [sp], #8 +UNWIND(.fnend) ENDPROC(__do_div64) diff --git a/arch/arm/lib/uaccess_with_memcpy.c b/arch/arm/lib/uaccess_with_memcpy.c index 8b9b13649f8170304245466a9409ce5e5ae2018b..025f742dd4df6bf79b279babd264980d851f01d5 100644 --- a/arch/arm/lib/uaccess_with_memcpy.c +++ b/arch/arm/lib/uaccess_with_memcpy.c @@ -17,6 +17,7 @@ #include #include /* for in_atomic() */ #include +#include #include #include diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 22484670e7ba60948d75aeb3af23009795a2fe37..a6b7991d7fe8462f325b903a11ea8da25e88f1ad 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -182,6 +182,11 @@ config MACH_ECO920 help Select this if you are using the eco920 board +config MACH_RSI_EWS + bool "RSI Embedded Webserver" + depends on ARCH_AT91RM9200 + help + Select this if you are using RSIs EWS board. endif # ---------------------------------------------------------- @@ -381,6 +386,14 @@ config MACH_GSIA18S This enables support for the GS_IA18_S board produced by GeoSIG Ltd company. This is an internet accelerograph. + +config MACH_USB_A9G20 + bool "CALAO USB-A9G20" + depends on ARCH_AT91SAM9G20 + help + Select this if you are using a Calao Systems USB-A9G20. + + endif if (ARCH_AT91SAM9260 || ARCH_AT91SAM9G20) @@ -442,6 +455,17 @@ endif # ---------------------------------------------------------- +comment "Generic Board Type" + +config MACH_AT91SAM_DT + bool "Atmel AT91SAM Evaluation Kits with device-tree support" + select USE_OF + help + Select this if you want to experiment device-tree with + an Atmel Evaluation Kit. + +# ---------------------------------------------------------- + comment "AT91 Board Options" config MTD_AT91_DATAFLASH_CARD diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index bf57e8b1c9d0b513e604ed356d391a095cbbf10e..242174f9f3554c6323075229eceef94a9f759225 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -36,12 +36,13 @@ obj-$(CONFIG_MACH_ECBAT91) += board-ecbat91.o obj-$(CONFIG_MACH_YL9200) += board-yl-9200.o obj-$(CONFIG_MACH_CPUAT91) += board-cpuat91.o obj-$(CONFIG_MACH_ECO920) += board-eco920.o +obj-$(CONFIG_MACH_RSI_EWS) += board-rsi-ews.o # AT91SAM9260 board-specific support obj-$(CONFIG_MACH_AT91SAM9260EK) += board-sam9260ek.o obj-$(CONFIG_MACH_CAM60) += board-cam60.o obj-$(CONFIG_MACH_SAM9_L9260) += board-sam9-l9260.o -obj-$(CONFIG_MACH_USB_A9260) += board-usb-a9260.o +obj-$(CONFIG_MACH_USB_A9260) += board-usb-a926x.o obj-$(CONFIG_MACH_QIL_A9260) += board-qil-a9260.o obj-$(CONFIG_MACH_AFEB9260) += board-afeb-9260v1.o obj-$(CONFIG_MACH_CPU9260) += board-cpu9krea.o @@ -53,7 +54,7 @@ obj-$(CONFIG_MACH_AT91SAM9G10EK) += board-sam9261ek.o # AT91SAM9263 board-specific support obj-$(CONFIG_MACH_AT91SAM9263EK) += board-sam9263ek.o -obj-$(CONFIG_MACH_USB_A9263) += board-usb-a9263.o +obj-$(CONFIG_MACH_USB_A9263) += board-usb-a926x.o obj-$(CONFIG_MACH_NEOCORE926) += board-neocore926.o # AT91SAM9RL board-specific support @@ -67,6 +68,7 @@ obj-$(CONFIG_MACH_STAMP9G20) += board-stamp9g20.o obj-$(CONFIG_MACH_PORTUXG20) += board-stamp9g20.o obj-$(CONFIG_MACH_PCONTROL_G20) += board-pcontrol-g20.o board-stamp9g20.o obj-$(CONFIG_MACH_GSIA18S) += board-gsia18s.o board-stamp9g20.o +obj-$(CONFIG_MACH_USB_A9G20) += board-usb-a926x.o # AT91SAM9260/AT91SAM9G20 board-specific support obj-$(CONFIG_MACH_SNAPPER_9260) += board-snapper9260.o @@ -74,6 +76,9 @@ obj-$(CONFIG_MACH_SNAPPER_9260) += board-snapper9260.o # AT91SAM9G45 board-specific support obj-$(CONFIG_MACH_AT91SAM9M10G45EK) += board-sam9m10g45ek.o +# AT91SAM board with device-tree +obj-$(CONFIG_MACH_AT91SAM_DT) += board-dt.o + # AT91CAP9 board-specific support obj-$(CONFIG_MACH_AT91CAP9ADK) += board-cap9adk.o diff --git a/arch/arm/mach-at91/Makefile.boot b/arch/arm/mach-at91/Makefile.boot index 3462b815054ace1695cfe1f5f9bddc3358e4d513..8ddafadfdc7dc94ac5f8319c5f56dc15fe798e8f 100644 --- a/arch/arm/mach-at91/Makefile.boot +++ b/arch/arm/mach-at91/Makefile.boot @@ -4,15 +4,17 @@ # INITRD_PHYS must be in RAM ifeq ($(CONFIG_ARCH_AT91CAP9),y) - zreladdr-y := 0x70008000 + zreladdr-y += 0x70008000 params_phys-y := 0x70000100 initrd_phys-y := 0x70410000 else ifeq ($(CONFIG_ARCH_AT91SAM9G45),y) - zreladdr-y := 0x70008000 + zreladdr-y += 0x70008000 params_phys-y := 0x70000100 initrd_phys-y := 0x70410000 else - zreladdr-y := 0x20008000 + zreladdr-y += 0x20008000 params_phys-y := 0x20000100 initrd_phys-y := 0x20410000 endif + +dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9m10g45ek.dtb usb_a9g20.dtb diff --git a/arch/arm/mach-at91/at91cap9.c b/arch/arm/mach-at91/at91cap9.c index bfc684441ef8db534154c15e05ac3f08de50ada7..ecdd54dd68c6c0139d10ca50595283bcf94545d7 100644 --- a/arch/arm/mach-at91/at91cap9.c +++ b/arch/arm/mach-at91/at91cap9.c @@ -219,6 +219,8 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk), + /* fake hclk clock */ + CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk), }; static struct clk_lookup usart_clocks_lookups[] = { diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c index dba0d8d8a4bd185dd96054cbc466b9a2a6c825d7..a4401d6b5b07b98f46492746f2cfbffc0a00d543 100644 --- a/arch/arm/mach-at91/at91cap9_devices.c +++ b/arch/arm/mach-at91/at91cap9_devices.c @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -23,7 +24,6 @@ #include #include -#include #include #include #include @@ -80,6 +80,12 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data) at91_set_gpio_output(data->vbus_pin[i], 0); } + /* Enable overcurrent notification */ + for (i = 0; i < data->ports; i++) { + if (data->overcurrent_pin[i]) + at91_set_gpio_input(data->overcurrent_pin[i], 1); + } + usbh_data = *data; platform_device_register(&at91_usbh_device); } diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c index f73302dbc6a547272624bee244224aa2fa06e520..713d3bdbd28447a7280adb746f4acc13af602cfd 100644 --- a/arch/arm/mach-at91/at91rm9200.c +++ b/arch/arm/mach-at91/at91rm9200.c @@ -193,6 +193,8 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk), + /* fake hclk clock */ + CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk), }; static struct clk_lookup usart_clocks_lookups[] = { diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c index 7227755ffec643fae52b92ebd71844581fb1ed92..01d8bbd1468ba5900990cd4cc2f53a37166c3281 100644 --- a/arch/arm/mach-at91/at91rm9200_devices.c +++ b/arch/arm/mach-at91/at91rm9200_devices.c @@ -14,11 +14,11 @@ #include #include +#include #include #include #include -#include #include #include @@ -60,9 +60,17 @@ static struct platform_device at91rm9200_usbh_device = { void __init at91_add_device_usbh(struct at91_usbh_data *data) { + int i; + if (!data) return; + /* Enable overcurrent notification */ + for (i = 0; i < data->ports; i++) { + if (data->overcurrent_pin[i]) + at91_set_gpio_input(data->overcurrent_pin[i], 1); + } + usbh_data = *data; platform_device_register(&at91rm9200_usbh_device); } diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c index cb397be14448eaa767ddbfd94bdf4fbdf8c25254..b84a9f642f5953a5ff527d3b593b1a628b61232b 100644 --- a/arch/arm/mach-at91/at91sam9260.c +++ b/arch/arm/mach-at91/at91sam9260.c @@ -199,6 +199,16 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("t4_clk", "atmel_tcb.1", &tc4_clk), CLKDEV_CON_DEV_ID("t5_clk", "atmel_tcb.1", &tc5_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc_clk), + /* more usart lookup table for DT entries */ + CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck), + CLKDEV_CON_DEV_ID("usart", "fffb0000.serial", &usart0_clk), + CLKDEV_CON_DEV_ID("usart", "fffb4000.serial", &usart1_clk), + CLKDEV_CON_DEV_ID("usart", "fffb8000.serial", &usart2_clk), + CLKDEV_CON_DEV_ID("usart", "fffd0000.serial", &usart3_clk), + CLKDEV_CON_DEV_ID("usart", "fffd4000.serial", &usart4_clk), + CLKDEV_CON_DEV_ID("usart", "fffd8000.serial", &usart5_clk), + /* fake hclk clock */ + CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk), }; static struct clk_lookup usart_clocks_lookups[] = { diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index 39f81f47b4ba4d4fe12c02e852cae1afb97b661b..24b6f8c0440ddc0c4b4661bc1bbf8b4f51c9b399 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -13,11 +13,11 @@ #include #include +#include #include #include #include -#include #include #include #include @@ -61,9 +61,17 @@ static struct platform_device at91_usbh_device = { void __init at91_add_device_usbh(struct at91_usbh_data *data) { + int i; + if (!data) return; + /* Enable overcurrent notification */ + for (i = 0; i < data->ports; i++) { + if (data->overcurrent_pin[i]) + at91_set_gpio_input(data->overcurrent_pin[i], 1); + } + usbh_data = *data; platform_device_register(&at91_usbh_device); } @@ -319,7 +327,7 @@ void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) if (!data) return; - for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) { + for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) { if (data->slot[i].bus_width) { /* input/irq */ if (data->slot[i].detect_pin) { diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c index 6c8e3b5f669ff7f7a3a885c43b8c1c7710ad2954..658a5185abfd44cf4671c5d5fa7c6f44b4fc229e 100644 --- a/arch/arm/mach-at91/at91sam9261.c +++ b/arch/arm/mach-at91/at91sam9261.c @@ -129,6 +129,20 @@ static struct clk lcdc_clk = { .type = CLK_TYPE_PERIPHERAL, }; +/* HClocks */ +static struct clk hck0 = { + .name = "hck0", + .pmc_mask = AT91_PMC_HCK0, + .type = CLK_TYPE_SYSTEM, + .id = 0, +}; +static struct clk hck1 = { + .name = "hck1", + .pmc_mask = AT91_PMC_HCK1, + .type = CLK_TYPE_SYSTEM, + .id = 1, +}; + static struct clk *periph_clocks[] __initdata = { &pioA_clk, &pioB_clk, @@ -161,6 +175,7 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk), + CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &hck0), }; static struct clk_lookup usart_clocks_lookups[] = { @@ -199,20 +214,6 @@ static struct clk pck3 = { .id = 3, }; -/* HClocks */ -static struct clk hck0 = { - .name = "hck0", - .pmc_mask = AT91_PMC_HCK0, - .type = CLK_TYPE_SYSTEM, - .id = 0, -}; -static struct clk hck1 = { - .name = "hck1", - .pmc_mask = AT91_PMC_HCK1, - .type = CLK_TYPE_SYSTEM, - .id = 1, -}; - static void __init at91sam9261_register_clocks(void) { int i; diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c index 0f917928eeb7782510f7b590d8e627a8b319795a..3b70b3897d950b5abc0f2f56cb68894b9e873b90 100644 --- a/arch/arm/mach-at91/at91sam9261_devices.c +++ b/arch/arm/mach-at91/at91sam9261_devices.c @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -21,7 +22,6 @@ #include