diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-22 19:02:13 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-22 19:02:13 -0400 |
| commit | 5d4e2d08e7fdf7339f84a1c670d296a77e02f881 (patch) | |
| tree | 1c419660defa56191091dfdf50fdb57a72009173 | |
| parent | fb2123fad3b499f0898835b19dbb93b18d27ee98 (diff) | |
| parent | 94ca629e40eb7e997be21d8065c25e4f3797b03f (diff) | |
Merge tag 'driver-core-3.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core
Pull driver core updates from Greg Kroah-Hartman:
"Here's the driver core, and other driver subsystems, pull request for
the 3.5-rc1 merge window.
Outside of a few minor driver core changes, we ended up with the
following different subsystem and core changes as well, due to
interdependancies on the driver core:
- hyperv driver updates
- drivers/memory being created and some drivers moved into it
- extcon driver subsystem created out of the old Android staging
switch driver code
- dynamic debug updates
- printk rework, and /dev/kmsg changes
All of this has been tested in the linux-next releases for a few weeks
with no reported problems.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>"
Fix up conflicts in drivers/extcon/extcon-max8997.c where git noticed
that a patch to the deleted drivers/misc/max8997-muic.c driver needs to
be applied to this one.
* tag 'driver-core-3.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (90 commits)
uio_pdrv_genirq: get irq through platform resource if not set otherwise
memory: tegra{20,30}-mc: Remove empty *_remove()
printk() - isolate KERN_CONT users from ordinary complete lines
sysfs: get rid of some lockdep false positives
Drivers: hv: util: Properly handle version negotiations.
Drivers: hv: Get rid of an unnecessary check in vmbus_prep_negotiate_resp()
memory: tegra{20,30}-mc: Use dev_err_ratelimited()
driver core: Add dev_*_ratelimited() family
Driver Core: don't oops with unregistered driver in driver_find_device()
printk() - restore prefix/timestamp printing for multi-newline strings
printk: add stub for prepend_timestamp()
ARM: tegra30: Make MC optional in Kconfig
ARM: tegra20: Make MC optional in Kconfig
ARM: tegra30: MC: Remove unnecessary BUG*()
ARM: tegra20: MC: Remove unnecessary BUG*()
printk: correctly align __log_buf
ARM: tegra30: Add Tegra Memory Controller(MC) driver
ARM: tegra20: Add Tegra Memory Controller(MC) driver
printk() - restore timestamp printing at console output
printk() - do not merge continuation lines of different threads
...
79 files changed, 6981 insertions, 1310 deletions
diff --git a/Documentation/ABI/testing/dev-kmsg b/Documentation/ABI/testing/dev-kmsg new file mode 100644 index 000000000000..281ecc5f9709 --- /dev/null +++ b/Documentation/ABI/testing/dev-kmsg | |||
| @@ -0,0 +1,90 @@ | |||
| 1 | What: /dev/kmsg | ||
| 2 | Date: Mai 2012 | ||
| 3 | KernelVersion: 3.5 | ||
| 4 | Contact: Kay Sievers <kay@vrfy.org> | ||
| 5 | Description: The /dev/kmsg character device node provides userspace access | ||
| 6 | to the kernel's printk buffer. | ||
| 7 | |||
| 8 | Injecting messages: | ||
| 9 | Every write() to the opened device node places a log entry in | ||
| 10 | the kernel's printk buffer. | ||
| 11 | |||
| 12 | The logged line can be prefixed with a <N> syslog prefix, which | ||
| 13 | carries the syslog priority and facility. The single decimal | ||
| 14 | prefix number is composed of the 3 lowest bits being the syslog | ||
| 15 | priority and the higher bits the syslog facility number. | ||
| 16 | |||
| 17 | If no prefix is given, the priority number is the default kernel | ||
| 18 | log priority and the facility number is set to LOG_USER (1). It | ||
| 19 | is not possible to inject messages from userspace with the | ||
| 20 | facility number LOG_KERN (0), to make sure that the origin of | ||
| 21 | the messages can always be reliably determined. | ||
| 22 | |||
| 23 | Accessing the buffer: | ||
| 24 | Every read() from the opened device node receives one record | ||
| 25 | of the kernel's printk buffer. | ||
| 26 | |||
| 27 | The first read() directly following an open() always returns | ||
| 28 | first message in the buffer; there is no kernel-internal | ||
| 29 | persistent state; many readers can concurrently open the device | ||
| 30 | and read from it, without affecting other readers. | ||
| 31 | |||
| 32 | Every read() will receive the next available record. If no more | ||
| 33 | records are available read() will block, or if O_NONBLOCK is | ||
| 34 | used -EAGAIN returned. | ||
| 35 | |||
| 36 | Messages in the record ring buffer get overwritten as whole, | ||
| 37 | there are never partial messages received by read(). | ||
| 38 | |||
| 39 | In case messages get overwritten in the circular buffer while | ||
| 40 | the device is kept open, the next read() will return -EPIPE, | ||
| 41 | and the seek position be updated to the next available record. | ||
| 42 | Subsequent reads() will return available records again. | ||
| 43 | |||
| 44 | Unlike the classic syslog() interface, the 64 bit record | ||
| 45 | sequence numbers allow to calculate the amount of lost | ||
| 46 | messages, in case the buffer gets overwritten. And they allow | ||
| 47 | to reconnect to the buffer and reconstruct the read position | ||
| 48 | if needed, without limiting the interface to a single reader. | ||
| 49 | |||
| 50 | The device supports seek with the following parameters: | ||
| 51 | SEEK_SET, 0 | ||
| 52 | seek to the first entry in the buffer | ||
| 53 | SEEK_END, 0 | ||
| 54 | seek after the last entry in the buffer | ||
| 55 | SEEK_DATA, 0 | ||
| 56 | seek after the last record available at the time | ||
| 57 | the last SYSLOG_ACTION_CLEAR was issued. | ||
| 58 | |||
| 59 | The output format consists of a prefix carrying the syslog | ||
| 60 | prefix including priority and facility, the 64 bit message | ||
| 61 | sequence number and the monotonic timestamp in microseconds. | ||
| 62 | The values are separated by a ','. Future extensions might | ||
| 63 | add more comma separated values before the terminating ';'. | ||
| 64 | Unknown values should be gracefully ignored. | ||
| 65 | |||
| 66 | The human readable text string starts directly after the ';' | ||
| 67 | and is terminated by a '\n'. Untrusted values derived from | ||
| 68 | hardware or other facilities are printed, therefore | ||
| 69 | all non-printable characters in the log message are escaped | ||
| 70 | by "\x00" C-style hex encoding. | ||
| 71 | |||
| 72 | A line starting with ' ', is a continuation line, adding | ||
| 73 | key/value pairs to the log message, which provide the machine | ||
| 74 | readable context of the message, for reliable processing in | ||
| 75 | userspace. | ||
| 76 | |||
| 77 | Example: | ||
| 78 | 7,160,424069;pci_root PNP0A03:00: host bridge window [io 0x0000-0x0cf7] (ignored) | ||
| 79 | SUBSYSTEM=acpi | ||
| 80 | DEVICE=+acpi:PNP0A03:00 | ||
| 81 | 6,339,5140900;NET: Registered protocol family 10 | ||
| 82 | 30,340,5690716;udevd[80]: starting version 181 | ||
| 83 | |||
| 84 | The DEVICE= key uniquely identifies devices the following way: | ||
| 85 | b12:8 - block dev_t | ||
| 86 | c127:3 - char dev_t | ||
| 87 | n8 - netdev ifindex | ||
| 88 | +sound:card0 - subsystem:devname | ||
| 89 | |||
| 90 | Users: dmesg(1), userspace kernel log consumers | ||
diff --git a/Documentation/ABI/testing/sysfs-class-extcon b/Documentation/ABI/testing/sysfs-class-extcon new file mode 100644 index 000000000000..20ab361bd8c6 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-extcon | |||
| @@ -0,0 +1,97 @@ | |||
| 1 | What: /sys/class/extcon/.../ | ||
| 2 | Date: February 2012 | ||
| 3 | Contact: MyungJoo Ham <myungjoo.ham@samsung.com> | ||
| 4 | Description: | ||
| 5 | Provide a place in sysfs for the extcon objects. | ||
| 6 | This allows accessing extcon specific variables. | ||
| 7 | The name of extcon object denoted as ... is the name given | ||
| 8 | with extcon_dev_register. | ||
| 9 | |||
| 10 | One extcon device denotes a single external connector | ||
| 11 | port. An external connector may have multiple cables | ||
| 12 | attached simultaneously. Many of docks, cradles, and | ||
| 13 | accessory cables have such capability. For example, | ||
| 14 | the 30-pin port of Nuri board (/arch/arm/mach-exynos) | ||
| 15 | may have both HDMI and Charger attached, or analog audio, | ||
| 16 | video, and USB cables attached simulteneously. | ||
| 17 | |||
| 18 | If there are cables mutually exclusive with each other, | ||
| 19 | such binary relations may be expressed with extcon_dev's | ||
| 20 | mutually_exclusive array. | ||
| 21 | |||
| 22 | What: /sys/class/extcon/.../name | ||
| 23 | Date: February 2012 | ||
| 24 | Contact: MyungJoo Ham <myungjoo.ham@samsung.com> | ||
| 25 | Description: | ||
| 26 | The /sys/class/extcon/.../name shows the name of the extcon | ||
| 27 | object. If the extcon object has an optional callback | ||
| 28 | "show_name" defined, the callback will provide the name with | ||
| 29 | this sysfs node. | ||
| 30 | |||
| 31 | What: /sys/class/extcon/.../state | ||
| 32 | Date: February 2012 | ||
| 33 | Contact: MyungJoo Ham <myungjoo.ham@samsung.com> | ||
| 34 | Description: | ||
| 35 | The /sys/class/extcon/.../state shows and stores the cable | ||
| 36 | attach/detach information of the corresponding extcon object. | ||
| 37 | If the extcon object has an optional callback "show_state" | ||
| 38 | defined, the showing function is overriden with the optional | ||
| 39 | callback. | ||
| 40 | |||
| 41 | If the default callback for showing function is used, the | ||
| 42 | format is like this: | ||
| 43 | # cat state | ||
| 44 | USB_OTG=1 | ||
| 45 | HDMI=0 | ||
| 46 | TA=1 | ||
| 47 | EAR_JACK=0 | ||
| 48 | # | ||
| 49 | In this example, the extcon device have USB_OTG and TA | ||
| 50 | cables attached and HDMI and EAR_JACK cables detached. | ||
| 51 | |||
| 52 | In order to update the state of an extcon device, enter a hex | ||
| 53 | state number starting with 0x. | ||
| 54 | echo 0xHEX > state | ||
| 55 | |||
| 56 | This updates the whole state of the extcon dev. | ||
| 57 | Inputs of all the methods are required to meet the | ||
| 58 | mutually_exclusive contidions if they exist. | ||
| 59 | |||
| 60 | It is recommended to use this "global" state interface if | ||
| 61 | you need to enter the value atomically. The later state | ||
| 62 | interface associated with each cable cannot update | ||
| 63 | multiple cable states of an extcon device simultaneously. | ||
| 64 | |||
| 65 | What: /sys/class/extcon/.../cable.x/name | ||
| 66 | Date: February 2012 | ||
| 67 | Contact: MyungJoo Ham <myungjoo.ham@samsung.com> | ||
| 68 | Description: | ||
| 69 | The /sys/class/extcon/.../cable.x/name shows the name of cable | ||
| 70 | "x" (integer between 0 and 31) of an extcon device. | ||
| 71 | |||
| 72 | What: /sys/class/extcon/.../cable.x/state | ||
| 73 | Date: February 2012 | ||
| 74 | Contact: MyungJoo Ham <myungjoo.ham@samsung.com> | ||
| 75 | Description: | ||
| 76 | The /sys/class/extcon/.../cable.x/name shows and stores the | ||
| 77 | state of cable "x" (integer between 0 and 31) of an extcon | ||
| 78 | device. The state value is either 0 (detached) or 1 | ||
| 79 | (attached). | ||
| 80 | |||
| 81 | What: /sys/class/extcon/.../mutually_exclusive/... | ||
| 82 | Date: December 2011 | ||
| 83 | Contact: MyungJoo Ham <myungjoo.ham@samsung.com> | ||
| 84 | Description: | ||
| 85 | Shows the relations of mutually exclusiveness. For example, | ||
| 86 | if the mutually_exclusive array of extcon_dev is | ||
| 87 | {0x3, 0x5, 0xC, 0x0}, the, the output is: | ||
| 88 | # ls mutually_exclusive/ | ||
| 89 | 0x3 | ||
| 90 | 0x5 | ||
| 91 | 0xc | ||
| 92 | # | ||
| 93 | |||
| 94 | Note that mutually_exclusive is a sub-directory of the extcon | ||
| 95 | device and the file names under the mutually_exclusive | ||
| 96 | directory show the mutually-exclusive sets, not the contents | ||
| 97 | of the files. | ||
diff --git a/Documentation/HOWTO b/Documentation/HOWTO index f7ade3b3b40d..59c080f084ef 100644 --- a/Documentation/HOWTO +++ b/Documentation/HOWTO | |||
| @@ -218,16 +218,16 @@ The development process | |||
| 218 | Linux kernel development process currently consists of a few different | 218 | Linux kernel development process currently consists of a few different |
| 219 | main kernel "branches" and lots of different subsystem-specific kernel | 219 | main kernel "branches" and lots of different subsystem-specific kernel |
| 220 | branches. These different branches are: | 220 | branches. These different branches are: |
| 221 | - main 2.6.x kernel tree | 221 | - main 3.x kernel tree |
| 222 | - 2.6.x.y -stable kernel tree | 222 | - 3.x.y -stable kernel tree |
| 223 | - 2.6.x -git kernel patches | 223 | - 3.x -git kernel patches |
| 224 | - subsystem specific kernel trees and patches | 224 | - subsystem specific kernel trees and patches |
| 225 | - the 2.6.x -next kernel tree for integration tests | 225 | - the 3.x -next kernel tree for integration tests |
| 226 | 226 | ||
| 227 | 2.6.x kernel tree | 227 | 3.x kernel tree |
| 228 | ----------------- | 228 | ----------------- |
| 229 | 2.6.x kernels are maintained by Linus Torvalds, and can be found on | 229 | 3.x kernels are maintained by Linus Torvalds, and can be found on |
| 230 | kernel.org in the pub/linux/kernel/v2.6/ directory. Its development | 230 | kernel.org in the pub/linux/kernel/v3.x/ directory. Its development |
| 231 | process is as follows: | 231 | process is as follows: |
| 232 | - As soon as a new kernel is released a two weeks window is open, | 232 | - As soon as a new kernel is released a two weeks window is open, |
| 233 | during this period of time maintainers can submit big diffs to | 233 | during this period of time maintainers can submit big diffs to |
| @@ -262,20 +262,20 @@ mailing list about kernel releases: | |||
| 262 | released according to perceived bug status, not according to a | 262 | released according to perceived bug status, not according to a |
| 263 | preconceived timeline." | 263 | preconceived timeline." |
| 264 | 264 | ||
| 265 | 2.6.x.y -stable kernel tree | 265 | 3.x.y -stable kernel tree |
| 266 | --------------------------- | 266 | --------------------------- |
| 267 | Kernels with 4-part versions are -stable kernels. They contain | 267 | Kernels with 3-part versions are -stable kernels. They contain |
| 268 | relatively small and critical fixes for security problems or significant | 268 | relatively small and critical fixes for security problems or significant |
| 269 | regressions discovered in a given 2.6.x kernel. | 269 | regressions discovered in a given 3.x kernel. |
| 270 | 270 | ||
| 271 | This is the recommended branch for users who want the most recent stable | 271 | This is the recommended branch for users who want the most recent stable |
| 272 | kernel and are not interested in helping test development/experimental | 272 | kernel and are not interested in helping test development/experimental |
| 273 | versions. | 273 | versions. |
| 274 | 274 | ||
| 275 | If no 2.6.x.y kernel is available, then the highest numbered 2.6.x | 275 | If no 3.x.y kernel is available, then the highest numbered 3.x |
| 276 | kernel is the current stable kernel. | 276 | kernel is the current stable kernel. |
| 277 | 277 | ||
| 278 | 2.6.x.y are maintained by the "stable" team <stable@vger.kernel.org>, and | 278 | 3.x.y are maintained by the "stable" team <stable@vger.kernel.org>, and |
| 279 | are released as needs dictate. The normal release period is approximately | 279 | are released as needs dictate. The normal release period is approximately |
| 280 | two weeks, but it can be longer if there are no pressing problems. A | 280 | two weeks, but it can be longer if there are no pressing problems. A |
| 281 | security-related problem, instead, can cause a release to happen almost | 281 | security-related problem, instead, can cause a release to happen almost |
| @@ -285,7 +285,7 @@ The file Documentation/stable_kernel_rules.txt in the kernel tree | |||
| 285 | documents what kinds of changes are acceptable for the -stable tree, and | 285 | documents what kinds of changes are acceptable for the -stable tree, and |
| 286 | how the release process works. | 286 | how the release process works. |
| 287 | 287 | ||
| 288 | 2.6.x -git patches | 288 | 3.x -git patches |
| 289 | ------------------ | 289 | ------------------ |
| 290 | These are daily snapshots of Linus' kernel tree which are managed in a | 290 | These are daily snapshots of Linus' kernel tree which are managed in a |
| 291 | git repository (hence the name.) These patches are usually released | 291 | git repository (hence the name.) These patches are usually released |
| @@ -317,13 +317,13 @@ revisions to it, and maintainers can mark patches as under review, | |||
| 317 | accepted, or rejected. Most of these patchwork sites are listed at | 317 | accepted, or rejected. Most of these patchwork sites are listed at |
| 318 | http://patchwork.kernel.org/. | 318 | http://patchwork.kernel.org/. |
| 319 | 319 | ||
| 320 | 2.6.x -next kernel tree for integration tests | 320 | 3.x -next kernel tree for integration tests |
| 321 | --------------------------------------------- | 321 | --------------------------------------------- |
| 322 | Before updates from subsystem trees are merged into the mainline 2.6.x | 322 | Before updates from subsystem trees are merged into the mainline 3.x |
| 323 | tree, they need to be integration-tested. For this purpose, a special | 323 | tree, they need to be integration-tested. For this purpose, a special |
| 324 | testing repository exists into which virtually all subsystem trees are | 324 | testing repository exists into which virtually all subsystem trees are |
| 325 | pulled on an almost daily basis: | 325 | pulled on an almost daily basis: |
| 326 | http://git.kernel.org/?p=linux/kernel/git/sfr/linux-next.git | 326 | http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git |
| 327 | http://linux.f-seidel.de/linux-next/pmwiki/ | 327 | http://linux.f-seidel.de/linux-next/pmwiki/ |
| 328 | 328 | ||
| 329 | This way, the -next kernel gives a summary outlook onto what will be | 329 | This way, the -next kernel gives a summary outlook onto what will be |
diff --git a/Documentation/devices.txt b/Documentation/devices.txt index 00383186d8fb..5941f5136c6b 100644 --- a/Documentation/devices.txt +++ b/Documentation/devices.txt | |||
| @@ -98,7 +98,8 @@ Your cooperation is appreciated. | |||
| 98 | 8 = /dev/random Nondeterministic random number gen. | 98 | 8 = /dev/random Nondeterministic random number gen. |
| 99 | 9 = /dev/urandom Faster, less secure random number gen. | 99 | 9 = /dev/urandom Faster, less secure random number gen. |
| 100 | 10 = /dev/aio Asynchronous I/O notification interface | 100 | 10 = /dev/aio Asynchronous I/O notification interface |
| 101 | 11 = /dev/kmsg Writes to this come out as printk's | 101 | 11 = /dev/kmsg Writes to this come out as printk's, reads |
| 102 | export the buffered printk records. | ||
| 102 | 12 = /dev/oldmem Used by crashdump kernels to access | 103 | 12 = /dev/oldmem Used by crashdump kernels to access |
| 103 | the memory of the kernel that crashed. | 104 | the memory of the kernel that crashed. |
| 104 | 105 | ||
diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-mc.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-mc.txt new file mode 100644 index 000000000000..c25a0a55151d --- /dev/null +++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-mc.txt | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | NVIDIA Tegra20 MC(Memory Controller) | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible : "nvidia,tegra20-mc" | ||
| 5 | - reg : Should contain 2 register ranges(address and length); see the | ||
| 6 | example below. Note that the MC registers are interleaved with the | ||
| 7 | GART registers, and hence must be represented as multiple ranges. | ||
| 8 | - interrupts : Should contain MC General interrupt. | ||
| 9 | |||
| 10 | Example: | ||
| 11 | mc { | ||
| 12 | compatible = "nvidia,tegra20-mc"; | ||
| 13 | reg = <0x7000f000 0x024 | ||
| 14 | 0x7000f03c 0x3c4>; | ||
| 15 | interrupts = <0 77 0x04>; | ||
| 16 | }; | ||
diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra30-mc.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra30-mc.txt new file mode 100644 index 000000000000..e47e73f612f4 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra30-mc.txt | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | NVIDIA Tegra30 MC(Memory Controller) | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible : "nvidia,tegra30-mc" | ||
| 5 | - reg : Should contain 4 register ranges(address and length); see the | ||
| 6 | example below. Note that the MC registers are interleaved with the | ||
| 7 | SMMU registers, and hence must be represented as multiple ranges. | ||
| 8 | - interrupts : Should contain MC General interrupt. | ||
| 9 | |||
| 10 | Example: | ||
| 11 | mc { | ||
| 12 | compatible = "nvidia,tegra30-mc"; | ||
| 13 | reg = <0x7000f000 0x010 | ||
| 14 | 0x7000f03c 0x1b4 | ||
| 15 | 0x7000f200 0x028 | ||
| 16 | 0x7000f284 0x17c>; | ||
| 17 | interrupts = <0 77 0x04>; | ||
| 18 | }; | ||
diff --git a/Documentation/dynamic-debug-howto.txt b/Documentation/dynamic-debug-howto.txt index 74e6c7782678..6e1684981da2 100644 --- a/Documentation/dynamic-debug-howto.txt +++ b/Documentation/dynamic-debug-howto.txt | |||
| @@ -2,17 +2,17 @@ | |||
| 2 | Introduction | 2 | Introduction |
| 3 | ============ | 3 | ============ |
| 4 | 4 | ||
| 5 | This document describes how to use the dynamic debug (ddebug) feature. | 5 | This document describes how to use the dynamic debug (dyndbg) feature. |
| 6 | 6 | ||
| 7 | Dynamic debug is designed to allow you to dynamically enable/disable kernel | 7 | Dynamic debug is designed to allow you to dynamically enable/disable |
| 8 | code to obtain additional kernel information. Currently, if | 8 | kernel code to obtain additional kernel information. Currently, if |
| 9 | CONFIG_DYNAMIC_DEBUG is set, then all pr_debug()/dev_dbg() calls can be | 9 | CONFIG_DYNAMIC_DEBUG is set, then all pr_debug()/dev_dbg() calls can |
| 10 | dynamically enabled per-callsite. | 10 | be dynamically enabled per-callsite. |
| 11 | 11 | ||
| 12 | Dynamic debug has even more useful features: | 12 | Dynamic debug has even more useful features: |
| 13 | 13 | ||
| 14 | * Simple query language allows turning on and off debugging statements by | 14 | * Simple query language allows turning on and off debugging |
| 15 | matching any combination of 0 or 1 of: | 15 | statements by matching any combination of 0 or 1 of: |
| 16 | 16 | ||
| 17 | - source filename | 17 | - source filename |
| 18 | - function name | 18 | - function name |
| @@ -20,17 +20,19 @@ Dynamic debug has even more useful features: | |||
| 20 | - module name | 20 | - module name |
| 21 | - format string | 21 | - format string |
| 22 | 22 | ||
| 23 | * Provides a debugfs control file: <debugfs>/dynamic_debug/control which can be | 23 | * Provides a debugfs control file: <debugfs>/dynamic_debug/control |
| 24 | read to display the complete list of known debug statements, to help guide you | 24 | which can be read to display the complete list of known debug |
| 25 | statements, to help guide you | ||
| 25 | 26 | ||
| 26 | Controlling dynamic debug Behaviour | 27 | Controlling dynamic debug Behaviour |
| 27 | =================================== | 28 | =================================== |
| 28 | 29 | ||
| 29 | The behaviour of pr_debug()/dev_dbg()s are controlled via writing to a | 30 | The behaviour of pr_debug()/dev_dbg()s are controlled via writing to a |
| 30 | control file in the 'debugfs' filesystem. Thus, you must first mount the debugfs | 31 | control file in the 'debugfs' filesystem. Thus, you must first mount |
| 31 | filesystem, in order to make use of this feature. Subsequently, we refer to the | 32 | the debugfs filesystem, in order to make use of this feature. |
| 32 | control file as: <debugfs>/dynamic_debug/control. For example, if you want to | 33 | Subsequently, we refer to the control file as: |
| 33 | enable printing from source file 'svcsock.c', line 1603 you simply do: | 34 | <debugfs>/dynamic_debug/control. For example, if you want to enable |
| 35 | printing from source file 'svcsock.c', line 1603 you simply do: | ||
| 34 | 36 | ||
| 35 | nullarbor:~ # echo 'file svcsock.c line 1603 +p' > | 37 | nullarbor:~ # echo 'file svcsock.c line 1603 +p' > |
| 36 | <debugfs>/dynamic_debug/control | 38 | <debugfs>/dynamic_debug/control |
| @@ -44,15 +46,15 @@ nullarbor:~ # echo 'file svcsock.c wtf 1 +p' > | |||
| 44 | Viewing Dynamic Debug Behaviour | 46 | Viewing Dynamic Debug Behaviour |
| 45 | =========================== | 47 | =========================== |
| 46 | 48 | ||
| 47 | You can view the currently configured behaviour of all the debug statements | 49 | You can view the currently configured behaviour of all the debug |
| 48 | via: | 50 | statements via: |
| 49 | 51 | ||
| 50 | nullarbor:~ # cat <debugfs>/dynamic_debug/control | 52 | nullarbor:~ # cat <debugfs>/dynamic_debug/control |
| 51 | # filename:lineno [module]function flags format | 53 | # filename:lineno [module]function flags format |
| 52 | /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:323 [svcxprt_rdma]svc_rdma_cleanup - "SVCRDMA Module Removed, deregister RPC RDMA transport\012" | 54 | /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:323 [svcxprt_rdma]svc_rdma_cleanup =_ "SVCRDMA Module Removed, deregister RPC RDMA transport\012" |
| 53 | /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:341 [svcxprt_rdma]svc_rdma_init - "\011max_inline : %d\012" | 55 | /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:341 [svcxprt_rdma]svc_rdma_init =_ "\011max_inline : %d\012" |
| 54 | /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:340 [svcxprt_rdma]svc_rdma_init - "\011sq_depth : %d\012" | 56 | /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:340 [svcxprt_rdma]svc_rdma_init =_ "\011sq_depth : %d\012" |
| 55 | /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:338 [svcxprt_rdma]svc_rdma_init - "\011max_requests : %d\012" | 57 | /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:338 [svcxprt_rdma]svc_rdma_init =_ "\011max_requests : %d\012" |
| 56 | ... | 58 | ... |
| 57 | 59 | ||
| 58 | 60 | ||
| @@ -65,12 +67,12 @@ nullarbor:~ # grep -i rdma <debugfs>/dynamic_debug/control | wc -l | |||
| 65 | nullarbor:~ # grep -i tcp <debugfs>/dynamic_debug/control | wc -l | 67 | nullarbor:~ # grep -i tcp <debugfs>/dynamic_debug/control | wc -l |
| 66 | 42 | 68 | 42 |
| 67 | 69 | ||
| 68 | Note in particular that the third column shows the enabled behaviour | 70 | The third column shows the currently enabled flags for each debug |
| 69 | flags for each debug statement callsite (see below for definitions of the | 71 | statement callsite (see below for definitions of the flags). The |
| 70 | flags). The default value, no extra behaviour enabled, is "-". So | 72 | default value, with no flags enabled, is "=_". So you can view all |
| 71 | you can view all the debug statement callsites with any non-default flags: | 73 | the debug statement callsites with any non-default flags: |
| 72 | 74 | ||
| 73 | nullarbor:~ # awk '$3 != "-"' <debugfs>/dynamic_debug/control | 75 | nullarbor:~ # awk '$3 != "=_"' <debugfs>/dynamic_debug/control |
| 74 | # filename:lineno [module]function flags format | 76 | # filename:lineno [module]function flags format |
| 75 | /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svcsock.c:1603 [sunrpc]svc_send p "svc_process: st_sendto returned %d\012" | 77 | /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svcsock.c:1603 [sunrpc]svc_send p "svc_process: st_sendto returned %d\012" |
| 76 | 78 | ||
| @@ -103,15 +105,14 @@ specifications, followed by a flags change specification. | |||
| 103 | 105 | ||
| 104 | command ::= match-spec* flags-spec | 106 | command ::= match-spec* flags-spec |
| 105 | 107 | ||
| 106 | The match-spec's are used to choose a subset of the known dprintk() | 108 | The match-spec's are used to choose a subset of the known pr_debug() |
| 107 | callsites to which to apply the flags-spec. Think of them as a query | 109 | callsites to which to apply the flags-spec. Think of them as a query |
| 108 | with implicit ANDs between each pair. Note that an empty list of | 110 | with implicit ANDs between each pair. Note that an empty list of |
| 109 | match-specs is possible, but is not very useful because it will not | 111 | match-specs will select all debug statement callsites. |
| 110 | match any debug statement callsites. | ||
| 111 | 112 | ||
| 112 | A match specification comprises a keyword, which controls the attribute | 113 | A match specification comprises a keyword, which controls the |
| 113 | of the callsite to be compared, and a value to compare against. Possible | 114 | attribute of the callsite to be compared, and a value to compare |
| 114 | keywords are: | 115 | against. Possible keywords are: |
| 115 | 116 | ||
| 116 | match-spec ::= 'func' string | | 117 | match-spec ::= 'func' string | |
| 117 | 'file' string | | 118 | 'file' string | |
| @@ -164,15 +165,15 @@ format | |||
| 164 | characters (") or single quote characters ('). | 165 | characters (") or single quote characters ('). |
| 165 | Examples: | 166 | Examples: |
| 166 | 167 | ||
| 167 | format svcrdma: // many of the NFS/RDMA server dprintks | 168 | format svcrdma: // many of the NFS/RDMA server pr_debugs |
| 168 | format readahead // some dprintks in the readahead cache | 169 | format readahead // some pr_debugs in the readahead cache |
| 169 | format nfsd:\040SETATTR // one way to match a format with whitespace | 170 | format nfsd:\040SETATTR // one way to match a format with whitespace |
| 170 | format "nfsd: SETATTR" // a neater way to match a format with whitespace | 171 | format "nfsd: SETATTR" // a neater way to match a format with whitespace |
| 171 | format 'nfsd: SETATTR' // yet another way to match a format with whitespace | 172 | format 'nfsd: SETATTR' // yet another way to match a format with whitespace |
| 172 | 173 | ||
| 173 | line | 174 | line |
| 174 | The given line number or range of line numbers is compared | 175 | The given line number or range of line numbers is compared |
| 175 | against the line number of each dprintk() callsite. A single | 176 | against the line number of each pr_debug() callsite. A single |
| 176 | line number matches the callsite line number exactly. A | 177 | line number matches the callsite line number exactly. A |
| 177 | range of line numbers matches any callsite between the first | 178 | range of line numbers matches any callsite between the first |
| 178 | and last line number inclusive. An empty first number means | 179 | and last line number inclusive. An empty first number means |
| @@ -188,51 +189,93 @@ The flags specification comprises a change operation followed | |||
| 188 | by one or more flag characters. The change operation is one | 189 | by one or more flag characters. The change operation is one |
| 189 | of the characters: | 190 | of the characters: |
| 190 | 191 | ||
| 191 | - | 192 | - remove the given flags |
| 192 | remove the given flags | 193 | + add the given flags |
| 193 | 194 | = set the flags to the given flags | |
| 194 | + | ||
| 195 | add the given flags | ||
| 196 | |||
| 197 | = | ||
| 198 | set the flags to the given flags | ||
| 199 | 195 | ||
| 200 | The flags are: | 196 | The flags are: |
| 201 | 197 | ||
| 202 | f | 198 | p enables the pr_debug() callsite. |
| 203 | Include the function name in the printed message | 199 | f Include the function name in the printed message |
| 204 | l | 200 | l Include line number in the printed message |
| 205 | Include line number in the printed message | 201 | m Include module name in the printed message |
| 206 | m | 202 | t Include thread ID in messages not generated from interrupt context |
| 207 | Include module name in the printed message | 203 | _ No flags are set. (Or'd with others on input) |
| 208 | p | 204 | |
| 209 | Causes a printk() message to be emitted to dmesg | 205 | For display, the flags are preceded by '=' |
| 210 | t | 206 | (mnemonic: what the flags are currently equal to). |
| 211 | Include thread ID in messages not generated from interrupt context | ||
| 212 | 207 | ||
| 213 | Note the regexp ^[-+=][flmpt]+$ matches a flags specification. | 208 | Note the regexp ^[-+=][flmpt_]+$ matches a flags specification. |
| 214 | Note also that there is no convenient syntax to remove all | 209 | To clear all flags at once, use "=_" or "-flmpt". |
| 215 | the flags at once, you need to use "-flmpt". | ||
| 216 | 210 | ||
| 217 | 211 | ||
| 218 | Debug messages during boot process | 212 | Debug messages during Boot Process |
| 219 | ================================== | 213 | ================================== |
| 220 | 214 | ||
| 221 | To be able to activate debug messages during the boot process, | 215 | To activate debug messages for core code and built-in modules during |
| 222 | even before userspace and debugfs exists, use the boot parameter: | 216 | the boot process, even before userspace and debugfs exists, use |
| 223 | ddebug_query="QUERY" | 217 | dyndbg="QUERY", module.dyndbg="QUERY", or ddebug_query="QUERY" |
| 218 | (ddebug_query is obsoleted by dyndbg, and deprecated). QUERY follows | ||
| 219 | the syntax described above, but must not exceed 1023 characters. Your | ||
| 220 | bootloader may impose lower limits. | ||
| 221 | |||
| 222 | These dyndbg params are processed just after the ddebug tables are | ||
| 223 | processed, as part of the arch_initcall. Thus you can enable debug | ||
| 224 | messages in all code run after this arch_initcall via this boot | ||
| 225 | parameter. | ||
| 224 | 226 | ||
| 225 | QUERY follows the syntax described above, but must not exceed 1023 | ||
| 226 | characters. The enablement of debug messages is done as an arch_initcall. | ||
| 227 | Thus you can enable debug messages in all code processed after this | ||
| 228 | arch_initcall via this boot parameter. | ||
| 229 | On an x86 system for example ACPI enablement is a subsys_initcall and | 227 | On an x86 system for example ACPI enablement is a subsys_initcall and |
| 230 | ddebug_query="file ec.c +p" | 228 | dyndbg="file ec.c +p" |
| 231 | will show early Embedded Controller transactions during ACPI setup if | 229 | will show early Embedded Controller transactions during ACPI setup if |
| 232 | your machine (typically a laptop) has an Embedded Controller. | 230 | your machine (typically a laptop) has an Embedded Controller. |
| 233 | PCI (or other devices) initialization also is a hot candidate for using | 231 | PCI (or other devices) initialization also is a hot candidate for using |
| 234 | this boot parameter for debugging purposes. | 232 | this boot parameter for debugging purposes. |
| 235 | 233 | ||
| 234 | If foo module is not built-in, foo.dyndbg will still be processed at | ||
| 235 | boot time, without effect, but will be reprocessed when module is | ||
| 236 | loaded later. dyndbg_query= and bare dyndbg= are only processed at | ||
| 237 | boot. | ||
| 238 | |||
| 239 | |||
| 240 | Debug Messages at Module Initialization Time | ||
| 241 | ============================================ | ||
| 242 | |||
| 243 | When "modprobe foo" is called, modprobe scans /proc/cmdline for | ||
| 244 | foo.params, strips "foo.", and passes them to the kernel along with | ||
| 245 | params given in modprobe args or /etc/modprob.d/*.conf files, | ||
| 246 | in the following order: | ||
| 247 | |||
| 248 | 1. # parameters given via /etc/modprobe.d/*.conf | ||
| 249 | options foo dyndbg=+pt | ||
| 250 | options foo dyndbg # defaults to +p | ||
| 251 | |||
| 252 | 2. # foo.dyndbg as given in boot args, "foo." is stripped and passed | ||
| 253 | foo.dyndbg=" func bar +p; func buz +mp" | ||
| 254 | |||
| 255 | 3. # args to modprobe | ||
| 256 | modprobe foo dyndbg==pmf # override previous settings | ||
| 257 | |||
| 258 | These dyndbg queries are applied in order, with last having final say. | ||
| 259 | This allows boot args to override or modify those from /etc/modprobe.d | ||
| 260 | (sensible, since 1 is system wide, 2 is kernel or boot specific), and | ||
| 261 | modprobe args to override both. | ||
| 262 | |||
| 263 | In the foo.dyndbg="QUERY" form, the query must exclude "module foo". | ||
| 264 | "foo" is extracted from the param-name, and applied to each query in | ||
| 265 | "QUERY", and only 1 match-spec of each type is allowed. | ||
| 266 | |||
| 267 | The dyndbg option is a "fake" module parameter, which means: | ||
| 268 | |||
| 269 | - modules do not need to define it explicitly | ||
| 270 | - every module gets it tacitly, whether they use pr_debug or not | ||
| 271 | - it doesnt appear in /sys/module/$module/parameters/ | ||
| 272 | To see it, grep the control file, or inspect /proc/cmdline. | ||
| 273 | |||
| 274 | For CONFIG_DYNAMIC_DEBUG kernels, any settings given at boot-time (or | ||
| 275 | enabled by -DDEBUG flag during compilation) can be disabled later via | ||
| 276 | the sysfs interface if the debug messages are no longer needed: | ||
| 277 | |||
| 278 | echo "module module_name -p" > <debugfs>/dynamic_debug/control | ||
| 236 | 279 | ||
| 237 | Examples | 280 | Examples |
| 238 | ======== | 281 | ======== |
| @@ -260,3 +303,18 @@ nullarbor:~ # echo -n 'func svc_process -p' > | |||
| 260 | // enable messages for NFS calls READ, READLINK, READDIR and READDIR+. | 303 | // enable messages for NFS calls READ, READLINK, READDIR and READDIR+. |
| 261 | nullarbor:~ # echo -n 'format "nfsd: READ" +p' > | 304 | nullarbor:~ # echo -n 'format "nfsd: READ" +p' > |
| 262 | <debugfs>/dynamic_debug/control | 305 | <debugfs>/dynamic_debug/control |
| 306 | |||
| 307 | // enable all messages | ||
| 308 | nullarbor:~ # echo -n '+p' > <debugfs>/dynamic_debug/control | ||
| 309 | |||
| 310 | // add module, function to all enabled messages | ||
| 311 | nullarbor:~ # echo -n '+mf' > <debugfs>/dynamic_debug/control | ||
| 312 | |||
| 313 | // boot-args example, with newlines and comments for readability | ||
| 314 | Kernel command line: ... | ||
| 315 | // see whats going on in dyndbg=value processing | ||
| 316 | dynamic_debug.verbose=1 | ||
| 317 | // enable pr_debugs in 2 builtins, #cmt is stripped | ||
| 318 | dyndbg="module params +p #cmt ; module sys +p" | ||
| 319 | // enable pr_debugs in 2 functions in a module loaded later | ||
| 320 | pc87360.dyndbg="func pc87360_init_device +p; func pc87360_find +p" | ||
diff --git a/Documentation/extcon/porting-android-switch-class b/Documentation/extcon/porting-android-switch-class new file mode 100644 index 000000000000..eb0fa5f4fe88 --- /dev/null +++ b/Documentation/extcon/porting-android-switch-class | |||
| @@ -0,0 +1,124 @@ | |||
| 1 | |||
| 2 | Staging/Android Switch Class Porting Guide | ||
| 3 | (linux/drivers/staging/android/switch) | ||
| 4 | (c) Copyright 2012 Samsung Electronics | ||
| 5 | |||
| 6 | AUTHORS | ||
| 7 | MyungJoo Ham <myungjoo.ham@samsung.com> | ||
| 8 | |||
| 9 | /***************************************************************** | ||
| 10 | * CHAPTER 1. * | ||
| 11 | * PORTING SWITCH CLASS DEVICE DRIVERS * | ||
| 12 | *****************************************************************/ | ||
| 13 | |||
| 14 | ****** STEP 1. Basic Functionality | ||
| 15 | No extcon extended feature, but switch features only. | ||
| 16 | |||
| 17 | - struct switch_dev (fed to switch_dev_register/unregister) | ||
| 18 | @name: no change | ||
| 19 | @dev: no change | ||
| 20 | @index: drop (not used in switch device driver side anyway) | ||
| 21 | @state: no change | ||
| 22 | If you have used @state with magic numbers, keep it | ||
| 23 | at this step. | ||
| 24 | @print_name: no change but type change (switch_dev->extcon_dev) | ||
| 25 | @print_state: no change but type change (switch_dev->extcon_dev) | ||
| 26 | |||
| 27 | - switch_dev_register(sdev, dev) | ||
| 28 | => extcon_dev_register(edev, dev) | ||
| 29 | : no change but type change (sdev->edev) | ||
| 30 | - switch_dev_unregister(sdev) | ||
| 31 | => extcon_dev_unregister(edev) | ||
| 32 | : no change but type change (sdev->edev) | ||
| 33 | - switch_get_state(sdev) | ||
| 34 | => extcon_get_state(edev) | ||
| 35 | : no change but type change (sdev->edev) and (return: int->u32) | ||
| 36 | - switch_set_state(sdev, state) | ||
| 37 | => extcon_set_state(edev, state) | ||
| 38 | : no change but type change (sdev->edev) and (state: int->u32) | ||
| 39 | |||
| 40 | With this changes, the ex-switch extcon class device works as it once | ||
| 41 | worked as switch class device. However, it will now have additional | ||
| 42 | interfaces (both ABI and in-kernel API) and different ABI locations. | ||
| 43 | However, if CONFIG_ANDROID is enabled without CONFIG_ANDROID_SWITCH, | ||
| 44 | /sys/class/switch/* will be symbolically linked to /sys/class/extcon/ | ||
| 45 | so that they are still compatible with legacy userspace processes. | ||
| 46 | |||
| 47 | ****** STEP 2. Multistate (no more magic numbers in state value) | ||
| 48 | Extcon's extended features for switch device drivers with | ||
| 49 | complex features usually required magic numbers in state | ||
| 50 | value of switch_dev. With extcon, such magic numbers that | ||
| 51 | support multiple cables ( | ||
| 52 | |||
| 53 | 1. Define cable names at edev->supported_cable. | ||
| 54 | 2. (Recommended) remove print_state callback. | ||
| 55 | 3. Use extcon_get_cable_state_(edev, index) or | ||
| 56 | extcon_get_cable_state(edev, cable_name) instead of | ||
| 57 | extcon_get_state(edev) if you intend to get a state of a specific | ||
| 58 | cable. Same for set_state. This way, you can remove the usage of | ||
| 59 | magic numbers in state value. | ||
| 60 | 4. Use extcon_update_state() if you are updating specific bits of | ||
| 61 | the state value. | ||
| 62 | |||
| 63 | Example: a switch device driver w/ magic numbers for two cables. | ||
| 64 | "0x00": no cables connected. | ||
| 65 | "0x01": cable 1 connected | ||
| 66 | "0x02": cable 2 connected | ||
| 67 | "0x03": cable 1 and 2 connected | ||
| 68 | 1. edev->supported_cable = {"1", "2", NULL}; | ||
| 69 | 2. edev->print_state = NULL; | ||
| 70 | 3. extcon_get_cable_state_(edev, 0) shows cable 1's state. | ||
| 71 | extcon_get_cable_state(edev, "1") shows cable 1's state. | ||
| 72 | extcon_set_cable_state_(edev, 1) sets cable 2's state. | ||
| 73 | extcon_set_cable_state(edev, "2") sets cable 2's state | ||
| 74 | 4. extcon_update_state(edev, 0x01, 0) sets the least bit's 0. | ||
| 75 | |||
| 76 | ****** STEP 3. Notify other device drivers | ||
| 77 | |||
| 78 | You can notify others of the cable attach/detach events with | ||
| 79 | notifier chains. | ||
| 80 | |||
| 81 | At the side of other device drivers (the extcon device itself | ||
| 82 | does not need to get notified of its own events), there are two | ||
| 83 | methods to register notifier_block for cable events: | ||
| 84 | (a) for a specific cable or (b) for every cable. | ||
| 85 | |||
| 86 | (a) extcon_register_interest(obj, extcon_name, cable_name, nb) | ||
| 87 | Example: want to get news of "MAX8997_MUIC"'s "USB" cable | ||
| 88 | |||
| 89 | obj = kzalloc(sizeof(struct extcon_specific_cable_nb), | ||
| 90 | GFP_KERNEL); | ||
| 91 | nb->notifier_call = the_callback_to_handle_usb; | ||
| 92 | |||
| 93 | extcon_register_intereset(obj, "MAX8997_MUIC", "USB", nb); | ||
| 94 | |||
| 95 | (b) extcon_register_notifier(edev, nb) | ||
| 96 | Call nb for any changes in edev. | ||
| 97 | |||
| 98 | Please note that in order to properly behave with method (a), | ||
| 99 | the extcon device driver should support multistate feature (STEP 2). | ||
| 100 | |||
| 101 | ****** STEP 4. Inter-cable relation (mutually exclusive) | ||
| 102 | |||
| 103 | You can provide inter-cable mutually exclusiveness information | ||
| 104 | for an extcon device. When cables A and B are declared to be mutually | ||
| 105 | exclusive, the two cables cannot be in ATTACHED state simulteneously. | ||
| 106 | |||
| 107 | |||
| 108 | /***************************************************************** | ||
| 109 | * CHAPTER 2. * | ||
| 110 | * PORTING USERSPACE w/ SWITCH CLASS DEVICE SUPPORT * | ||
| 111 | *****************************************************************/ | ||
| 112 | |||
| 113 | ****** ABI Location | ||
| 114 | |||
| 115 | If "CONFIG_ANDROID" is enabled and "CONFIG_ANDROID_SWITCH" is | ||
| 116 | disabled, /sys/class/switch/* are created as symbolic links to | ||
| 117 | /sys/class/extcon/*. Because CONFIG_ANDROID_SWITCH creates | ||
| 118 | /sys/class/switch directory, we disable symboling linking if | ||
| 119 | CONFIG_ANDROID_SWITCH is enabled. | ||
| 120 | |||
| 121 | The two files of switch class, name and state, are provided with | ||
| 122 | extcon, too. When the multistate support (STEP 2 of CHAPTER 1.) is | ||
| 123 | not enabled or print_state callback is supplied, the output of | ||
| 124 | state ABI is same with switch class. | ||
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index e4b57756b9f5..e9abede594e1 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt | |||
| @@ -2,7 +2,14 @@ The following is a list of files and features that are going to be | |||
| 2 | removed in the kernel source tree. Every entry should contain what | 2 | removed in the kernel source tree. Every entry should contain what |
| 3 | exactly is going away, why it is happening, and who is going to be doing | 3 | exactly is going away, why it is happening, and who is going to be doing |
| 4 | the work. When the feature is removed from the kernel, it should also | 4 | the work. When the feature is removed from the kernel, it should also |
| 5 | be removed from this file. | 5 | be removed from this file. The suggested deprecation period is 3 releases. |
| 6 | |||
| 7 | --------------------------- | ||
| 8 | |||
| 9 | What: ddebug_query="query" boot cmdline param | ||
| 10 | When: v3.8 | ||
| 11 | Why: obsoleted by dyndbg="query" and module.dyndbg="query" | ||
| 12 | Who: Jim Cromie <jim.cromie@gmail.com>, Jason Baron <jbaron@redhat.com> | ||
| 6 | 13 | ||
| 7 | --------------------------- | 14 | --------------------------- |
| 8 | 15 | ||
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index e275432ef2c7..62aba89b04a2 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
| @@ -611,7 +611,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
| 611 | 611 | ||
| 612 | ddebug_query= [KNL,DYNAMIC_DEBUG] Enable debug messages at early boot | 612 | ddebug_query= [KNL,DYNAMIC_DEBUG] Enable debug messages at early boot |
| 613 | time. See Documentation/dynamic-debug-howto.txt for | 613 | time. See Documentation/dynamic-debug-howto.txt for |
| 614 | details. | 614 | details. Deprecated, see dyndbg. |
| 615 | 615 | ||
| 616 | debug [KNL] Enable kernel debugging (events log level). | 616 | debug [KNL] Enable kernel debugging (events log level). |
| 617 | 617 | ||
| @@ -731,6 +731,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
| 731 | 731 | ||
| 732 | dscc4.setup= [NET] | 732 | dscc4.setup= [NET] |
| 733 | 733 | ||
| 734 | dyndbg[="val"] [KNL,DYNAMIC_DEBUG] | ||
| 735 | module.dyndbg[="val"] | ||
| 736 | Enable debug messages at boot time. See | ||
| 737 | Documentation/dynamic-debug-howto.txt for details. | ||
| 738 | |||
| 734 | earlycon= [KNL] Output early console device and options. | 739 | earlycon= [KNL] Output early console device and options. |
| 735 | uart[8250],io,<addr>[,options] | 740 | uart[8250],io,<addr>[,options] |
| 736 | uart[8250],mmio,<addr>[,options] | 741 | uart[8250],mmio,<addr>[,options] |
diff --git a/Documentation/memory-devices/ti-emif.txt b/Documentation/memory-devices/ti-emif.txt new file mode 100644 index 000000000000..f4ad9a7d0f4b --- /dev/null +++ b/Documentation/memory-devices/ti-emif.txt | |||
| @@ -0,0 +1,57 @@ | |||
| 1 | TI EMIF SDRAM Controller Driver: | ||
| 2 | |||
| 3 | Author | ||
| 4 | ======== | ||
| 5 | Aneesh V <aneesh@ti.com> | ||
| 6 | |||
| 7 | Location | ||
| 8 | ============ | ||
| 9 | driver/memory/emif.c | ||
| 10 | |||
| 11 | Supported SoCs: | ||
| 12 | =================== | ||
| 13 | TI OMAP44xx | ||
| 14 | TI OMAP54xx | ||
| 15 | |||
| 16 | Menuconfig option: | ||
| 17 | ========================== | ||
| 18 | Device Drivers | ||
| 19 | Memory devices | ||
| 20 | Texas Instruments EMIF driver | ||
| 21 | |||
| 22 | Description | ||
| 23 | =========== | ||
| 24 | This driver is for the EMIF module available in Texas Instruments | ||
| 25 | SoCs. EMIF is an SDRAM controller that, based on its revision, | ||
| 26 | supports one or more of DDR2, DDR3, and LPDDR2 SDRAM protocols. | ||
| 27 | This driver takes care of only LPDDR2 memories presently. The | ||
| 28 | functions of the driver includes re-configuring AC timing | ||
| 29 | parameters and other settings during frequency, voltage and | ||
| 30 | temperature changes | ||
| 31 | |||
| 32 | Platform Data (see include/linux/platform_data/emif_plat.h): | ||
| 33 | ===================================================================== | ||
| 34 | DDR device details and other board dependent and SoC dependent | ||
| 35 | information can be passed through platform data (struct emif_platform_data) | ||
| 36 | - DDR device details: 'struct ddr_device_info' | ||
| 37 | - Device AC timings: 'struct lpddr2_timings' and 'struct lpddr2_min_tck' | ||
| 38 | - Custom configurations: customizable policy options through | ||
| 39 | 'struct emif_custom_configs' | ||
| 40 | - IP revision | ||
| 41 | - PHY type | ||
| 42 | |||
| 43 | Interface to the external world: | ||
| 44 | ================================ | ||
| 45 | EMIF driver registers notifiers for voltage and frequency changes | ||
| 46 | affecting EMIF and takes appropriate actions when these are invoked. | ||
| 47 | - freq_pre_notify_handling() | ||
| 48 | - freq_post_notify_handling() | ||
| 49 | - volt_notify_handling() | ||
| 50 | |||
| 51 | Debugfs | ||
| 52 | ======== | ||
| 53 | The driver creates two debugfs entries per device. | ||
| 54 | - regcache_dump : dump of register values calculated and saved for all | ||
| 55 | frequencies used so far. | ||
| 56 | - mr4 : last polled value of MR4 register in the LPDDR2 device. MR4 | ||
| 57 | indicates the current temperature level of the device. | ||
diff --git a/Documentation/zh_CN/magic-number.txt b/Documentation/zh_CN/magic-number.txt index f606ba8598cf..4263022f5002 100644 --- a/Documentation/zh_CN/magic-number.txt +++ b/Documentation/zh_CN/magic-number.txt | |||
| @@ -160,7 +160,7 @@ QUEUE_MAGIC_USED 0xf7e1cc33 queue_entry drivers/scsi/arm/queue.c | |||
| 160 | HTB_CMAGIC 0xFEFAFEF1 htb_class net/sched/sch_htb.c | 160 | HTB_CMAGIC 0xFEFAFEF1 htb_class net/sched/sch_htb.c |
| 161 | NMI_MAGIC 0x48414d4d455201 nmi_s arch/mips/include/asm/sn/nmi.h | 161 | NMI_MAGIC 0x48414d4d455201 nmi_s arch/mips/include/asm/sn/nmi.h |
| 162 | 162 | ||
| 163 | 请注意,在声音记忆管理中仍然有每一些被定义的驱动魔术值。查看include/sound/sndmagic.h来获取他们完整的列表信息。很多OSS声音驱动拥有自己从声卡PCI ID构建的魔术值-他们也没有被列在这里。 | 163 | 请注意,在声音记忆管理中仍然有一些特殊的为每个驱动定义的魔术值。查看include/sound/sndmagic.h来获取他们完整的列表信息。很多OSS声音驱动拥有自己从声卡PCI ID构建的魔术值-他们也没有被列在这里。 |
| 164 | 164 | ||
| 165 | IrDA子系统也使用了大量的自己的魔术值,查看include/net/irda/irda.h来获取他们完整的信息。 | 165 | IrDA子系统也使用了大量的自己的魔术值,查看include/net/irda/irda.h来获取他们完整的信息。 |
| 166 | 166 | ||
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index fb05b123218f..1a6de0a7d8eb 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c | |||
| @@ -271,7 +271,8 @@ int alloc_bootmem_huge_page(struct hstate *hstate) | |||
| 271 | 271 | ||
| 272 | unsigned long gpage_npages[MMU_PAGE_COUNT]; | 272 | unsigned long gpage_npages[MMU_PAGE_COUNT]; |
| 273 | 273 | ||
| 274 | static int __init do_gpage_early_setup(char *param, char *val) | 274 | static int __init do_gpage_early_setup(char *param, char *val, |
| 275 | const char *unused) | ||
| 275 | { | 276 | { |
| 276 | static phys_addr_t size; | 277 | static phys_addr_t size; |
| 277 | unsigned long npages; | 278 | unsigned long npages; |
diff --git a/drivers/Kconfig b/drivers/Kconfig index d236aef7e59f..63b81826cb55 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig | |||
| @@ -140,4 +140,8 @@ source "drivers/virt/Kconfig" | |||
| 140 | 140 | ||
| 141 | source "drivers/devfreq/Kconfig" | 141 | source "drivers/devfreq/Kconfig" |
| 142 | 142 | ||
| 143 | source "drivers/extcon/Kconfig" | ||
| 144 | |||
| 145 | source "drivers/memory/Kconfig" | ||
| 146 | |||
| 143 | endmenu | 147 | endmenu |
diff --git a/drivers/Makefile b/drivers/Makefile index 95952c82bf16..265b506a15be 100644 --- a/drivers/Makefile +++ b/drivers/Makefile | |||
| @@ -134,3 +134,5 @@ obj-$(CONFIG_VIRT_DRIVERS) += virt/ | |||
| 134 | obj-$(CONFIG_HYPERV) += hv/ | 134 | obj-$(CONFIG_HYPERV) += hv/ |
| 135 | 135 | ||
| 136 | obj-$(CONFIG_PM_DEVFREQ) += devfreq/ | 136 | obj-$(CONFIG_PM_DEVFREQ) += devfreq/ |
| 137 | obj-$(CONFIG_EXTCON) += extcon/ | ||
| 138 | obj-$(CONFIG_MEMORY) += memory/ | ||
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 4a29763b8eb4..a12808259dfb 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c | |||
| @@ -720,21 +720,21 @@ static int acpi_pci_link_add(struct acpi_device *device) | |||
| 720 | acpi_device_bid(device)); | 720 | acpi_device_bid(device)); |
| 721 | for (i = 0; i < link->irq.possible_count; i++) { | 721 | for (i = 0; i < link->irq.possible_count; i++) { |
| 722 | if (link->irq.active == link->irq.possible[i]) { | 722 | if (link->irq.active == link->irq.possible[i]) { |
| 723 | printk(" *%d", link->irq.possible[i]); | 723 | printk(KERN_CONT " *%d", link->irq.possible[i]); |
| 724 | found = 1; | 724 | found = 1; |
| 725 | } else | 725 | } else |
| 726 | printk(" %d", link->irq.possible[i]); | 726 | printk(KERN_CONT " %d", link->irq.possible[i]); |
| 727 | } | 727 | } |
| 728 | 728 | ||
| 729 | printk(")"); | 729 | printk(KERN_CONT ")"); |
| 730 | 730 | ||
| 731 | if (!found) | 731 | if (!found) |
| 732 | printk(" *%d", link->irq.active); | 732 | printk(KERN_CONT " *%d", link->irq.active); |
| 733 | 733 | ||
| 734 | if (!link->device->status.enabled) | 734 | if (!link->device->status.enabled) |
| 735 | printk(", disabled."); | 735 | printk(KERN_CONT ", disabled."); |
| 736 | 736 | ||
| 737 | printk("\n"); | 737 | printk(KERN_CONT "\n"); |
| 738 | 738 | ||
| 739 | list_add_tail(&link->list, &acpi_link_list); | 739 | list_add_tail(&link->list, &acpi_link_list); |
| 740 | 740 | ||
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index eb6fd233764b..06527c526618 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
| @@ -887,7 +887,7 @@ int __init acpi_sleep_init(void) | |||
| 887 | status = acpi_get_sleep_type_data(i, &type_a, &type_b); | 887 | status = acpi_get_sleep_type_data(i, &type_a, &type_b); |
| 888 | if (ACPI_SUCCESS(status)) { | 888 | if (ACPI_SUCCESS(status)) { |
| 889 | sleep_states[i] = 1; | 889 | sleep_states[i] = 1; |
| 890 | printk(" S%d", i); | 890 | printk(KERN_CONT " S%d", i); |
| 891 | } | 891 | } |
| 892 | } | 892 | } |
| 893 | 893 | ||
| @@ -901,7 +901,7 @@ int __init acpi_sleep_init(void) | |||
| 901 | hibernation_set_ops(old_suspend_ordering ? | 901 | hibernation_set_ops(old_suspend_ordering ? |
| 902 | &acpi_hibernation_ops_old : &acpi_hibernation_ops); | 902 | &acpi_hibernation_ops_old : &acpi_hibernation_ops); |
| 903 | sleep_states[ACPI_STATE_S4] = 1; | 903 | sleep_states[ACPI_STATE_S4] = 1; |
| 904 | printk(" S4"); | 904 | printk(KERN_CONT " S4"); |
| 905 | if (!nosigcheck) { | 905 | if (!nosigcheck) { |
| 906 | acpi_get_table(ACPI_SIG_FACS, 1, | 906 | acpi_get_table(ACPI_SIG_FACS, 1, |
| 907 | (struct acpi_table_header **)&facs); | 907 | (struct acpi_table_header **)&facs); |
| @@ -914,11 +914,11 @@ int __init acpi_sleep_init(void) | |||
| 914 | status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b); | 914 | status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b); |
| 915 | if (ACPI_SUCCESS(status)) { | 915 | if (ACPI_SUCCESS(status)) { |
| 916 | sleep_states[ACPI_STATE_S5] = 1; | 916 | sleep_states[ACPI_STATE_S5] = 1; |
| 917 | printk(" S5"); | 917 | printk(KERN_CONT " S5"); |
| 918 | pm_power_off_prepare = acpi_power_off_prepare; | 918 | pm_power_off_prepare = acpi_power_off_prepare; |
| 919 | pm_power_off = acpi_power_off; | 919 | pm_power_off = acpi_power_off; |
| 920 | } | 920 | } |
| 921 | printk(")\n"); | 921 | printk(KERN_CONT ")\n"); |
| 922 | /* | 922 | /* |
| 923 | * Register the tts_notifier to reboot notifier list so that the _TTS | 923 | * Register the tts_notifier to reboot notifier list so that the _TTS |
| 924 | * object can also be evaluated when the system enters S5. | 924 | * object can also be evaluated when the system enters S5. |
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 26a06b801b5b..2bcef657a60c 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c | |||
| @@ -21,8 +21,7 @@ | |||
| 21 | #include "power/power.h" | 21 | #include "power/power.h" |
| 22 | 22 | ||
| 23 | /* /sys/devices/system */ | 23 | /* /sys/devices/system */ |
| 24 | /* FIXME: make static after drivers/base/sys.c is deleted */ | 24 | static struct kset *system_kset; |
| 25 | struct kset *system_kset; | ||
| 26 | 25 | ||
| 27 | #define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr) | 26 | #define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr) |
| 28 | 27 | ||
diff --git a/drivers/base/core.c b/drivers/base/core.c index e28ce9898af4..346be8b78b24 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <linux/mutex.h> | 25 | #include <linux/mutex.h> |
| 26 | #include <linux/async.h> | 26 | #include <linux/async.h> |
| 27 | #include <linux/pm_runtime.h> | 27 | #include <linux/pm_runtime.h> |
| 28 | #include <linux/netdevice.h> | ||
| 28 | 29 | ||
| 29 | #include "base.h" | 30 | #include "base.h" |
| 30 | #include "power/power.h" | 31 | #include "power/power.h" |
| @@ -65,7 +66,7 @@ static inline int device_is_not_partition(struct device *dev) | |||
| 65 | * @dev: struct device to get the name of | 66 | * @dev: struct device to get the name of |
| 66 | * | 67 | * |
| 67 | * Will return the device's driver's name if it is bound to a device. If | 68 | * Will return the device's driver's name if it is bound to a device. If |
| 68 | * the device is not bound to a device, it will return the name of the bus | 69 | * the device is not bound to a driver, it will return the name of the bus |
| 69 | * it is attached to. If it is not attached to a bus either, an empty | 70 | * it is attached to. If it is not attached to a bus either, an empty |
| 70 | * string will be returned. | 71 | * string will be returned. |
| 71 | */ | 72 | */ |
| @@ -878,8 +879,8 @@ EXPORT_SYMBOL_GPL(dev_set_name); | |||
| 878 | * to NULL prevents an entry from being created. class->dev_kobj must | 879 | * to NULL prevents an entry from being created. class->dev_kobj must |
| 879 | * be set (or cleared) before any devices are registered to the class | 880 | * be set (or cleared) before any devices are registered to the class |
| 880 | * otherwise device_create_sys_dev_entry() and | 881 | * otherwise device_create_sys_dev_entry() and |
| 881 | * device_remove_sys_dev_entry() will disagree about the the presence | 882 | * device_remove_sys_dev_entry() will disagree about the presence of |
| 882 | * of the link. | 883 | * the link. |
| 883 | */ | 884 | */ |
| 884 | static struct kobject *device_to_dev_kobj(struct device *dev) | 885 | static struct kobject *device_to_dev_kobj(struct device *dev) |
| 885 | { | 886 | { |
| @@ -1843,15 +1844,60 @@ void device_shutdown(void) | |||
| 1843 | */ | 1844 | */ |
| 1844 | 1845 | ||
| 1845 | #ifdef CONFIG_PRINTK | 1846 | #ifdef CONFIG_PRINTK |
| 1846 | |||
| 1847 | int __dev_printk(const char *level, const struct device *dev, | 1847 | int __dev_printk(const char *level, const struct device *dev, |
| 1848 | struct va_format *vaf) | 1848 | struct va_format *vaf) |
| 1849 | { | 1849 | { |
| 1850 | char dict[128]; | ||
| 1851 | size_t dictlen = 0; | ||
| 1852 | const char *subsys; | ||
| 1853 | |||
| 1850 | if (!dev) | 1854 | if (!dev) |
| 1851 | return printk("%s(NULL device *): %pV", level, vaf); | 1855 | return printk("%s(NULL device *): %pV", level, vaf); |
| 1852 | 1856 | ||
| 1853 | return printk("%s%s %s: %pV", | 1857 | if (dev->class) |
| 1854 | level, dev_driver_string(dev), dev_name(dev), vaf); | 1858 | subsys = dev->class->name; |
| 1859 | else if (dev->bus) | ||
| 1860 | subsys = dev->bus->name; | ||
| 1861 | else | ||
| 1862 | goto skip; | ||
| 1863 | |||
| 1864 | dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen, | ||
| 1865 | "SUBSYSTEM=%s", subsys); | ||
| 1866 | |||
| 1867 | /* | ||
| 1868 | * Add device identifier DEVICE=: | ||
| 1869 | * b12:8 block dev_t | ||
| 1870 | * c127:3 char dev_t | ||
| 1871 | * n8 netdev ifindex | ||
| 1872 | * +sound:card0 subsystem:devname | ||
| 1873 | */ | ||
| 1874 | if (MAJOR(dev->devt)) { | ||
| 1875 | char c; | ||
| 1876 | |||
| 1877 | if (strcmp(subsys, "block") == 0) | ||
| 1878 | c = 'b'; | ||
| 1879 | else | ||
| 1880 | c = 'c'; | ||
| 1881 | dictlen++; | ||
| 1882 | dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen, | ||
| 1883 | "DEVICE=%c%u:%u", | ||
| 1884 | c, MAJOR(dev->devt), MINOR(dev->devt)); | ||
| 1885 | } else if (strcmp(subsys, "net") == 0) { | ||
| 1886 | struct net_device *net = to_net_dev(dev); | ||
| 1887 | |||
| 1888 | dictlen++; | ||
| 1889 | dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen, | ||
| 1890 | "DEVICE=n%u", net->ifindex); | ||
| 1891 | } else { | ||
| 1892 | dictlen++; | ||
| 1893 | dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen, | ||
| 1894 | "DEVICE=+%s:%s", subsys, dev_name(dev)); | ||
| 1895 | } | ||
| 1896 | skip: | ||
| 1897 | return printk_emit(0, level[1] - '0', | ||
| 1898 | dictlen ? dict : NULL, dictlen, | ||
| 1899 | "%s %s: %pV", | ||
| 1900 | dev_driver_string(dev), dev_name(dev), vaf); | ||
| 1855 | } | 1901 | } |
| 1856 | EXPORT_SYMBOL(__dev_printk); | 1902 | EXPORT_SYMBOL(__dev_printk); |
| 1857 | 1903 | ||
diff --git a/drivers/base/devres.c b/drivers/base/devres.c index 524bf96c289f..2360adb7a58f 100644 --- a/drivers/base/devres.c +++ b/drivers/base/devres.c | |||
| @@ -309,6 +309,10 @@ EXPORT_SYMBOL_GPL(devres_remove); | |||
| 309 | * which @match returns 1. If @match is NULL, it's considered to | 309 | * which @match returns 1. If @match is NULL, it's considered to |
| 310 | * match all. If found, the resource is removed atomically and freed. | 310 | * match all. If found, the resource is removed atomically and freed. |
| 311 | * | 311 | * |
| 312 | * Note that the release function for the resource will not be called, | ||
| 313 | * only the devres-allocated data will be freed. The caller becomes | ||
| 314 | * responsible for freeing any other data. | ||
| 315 | * | ||
| 312 | * RETURNS: | 316 | * RETURNS: |
| 313 | * 0 if devres is found and freed, -ENOENT if not found. | 317 | * 0 if devres is found and freed, -ENOENT if not found. |
| 314 | */ | 318 | */ |
| @@ -326,6 +330,37 @@ int devres_destroy(struct device *dev, dr_release_t release, | |||
| 326 | } | 330 | } |
| 327 | EXPORT_SYMBOL_GPL(devres_destroy); | 331 | EXPORT_SYMBOL_GPL(devres_destroy); |
| 328 | 332 | ||
| 333 | |||
| 334 | /** | ||
| 335 | * devres_release - Find a device resource and destroy it, calling release | ||
| 336 | * @dev: Device to find resource from | ||
| 337 | * @release: Look for resources associated with this release function | ||
| 338 | * @match: Match function (optional) | ||
| 339 | * @match_data: Data for the match function | ||
| 340 | * | ||
| 341 | * Find the latest devres of @dev associated with @release and for | ||
| 342 | * which @match returns 1. If @match is NULL, it's considered to | ||
| 343 | * match all. If found, the resource is removed atomically, the | ||
| 344 | * release function called and the resource freed. | ||
| 345 | * | ||
| 346 | * RETURNS: | ||
| 347 | * 0 if devres is found and freed, -ENOENT if not found. | ||
| 348 | */ | ||
| 349 | int devres_release(struct device *dev, dr_release_t release, | ||
| 350 | dr_match_t match, void *match_data) | ||
| 351 | { | ||
| 352 | void *res; | ||
| 353 | |||
| 354 | res = devres_remove(dev, release, match, match_data); | ||
| 355 | if (unlikely(!res)) | ||
| 356 | return -ENOENT; | ||
| 357 | |||
| 358 | (*release)(dev, res); | ||
| 359 | devres_free(res); | ||
| 360 | return 0; | ||
| 361 | } | ||
| 362 | EXPORT_SYMBOL_GPL(devres_release); | ||
| 363 | |||
| 329 | static int remove_nodes(struct device *dev, | 364 | static int remove_nodes(struct device *dev, |
| 330 | struct list_head *first, struct list_head *end, | 365 | struct list_head *first, struct list_head *end, |
| 331 | struct list_head *todo) | 366 | struct list_head *todo) |
diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index 8493536ea55b..765c3a28077a 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c | |||
| @@ -7,9 +7,9 @@ | |||
| 7 | * devtmpfs, a tmpfs-based filesystem is created. Every driver-core | 7 | * devtmpfs, a tmpfs-based filesystem is created. Every driver-core |
| 8 | * device which requests a device node, will add a node in this | 8 | * device which requests a device node, will add a node in this |
| 9 | * filesystem. | 9 | * filesystem. |
| 10 | * By default, all devices are named after the the name of the | 10 | * By default, all devices are named after the name of the device, |
| 11 | * device, owned by root and have a default mode of 0600. Subsystems | 11 | * owned by root and have a default mode of 0600. Subsystems can |
| 12 | * can overwrite the default setting if needed. | 12 | * overwrite the default setting if needed. |
| 13 | */ | 13 | */ |
| 14 | 14 | ||
| 15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c index 07cbbc6fddb4..05c64c11bad2 100644 --- a/drivers/base/dma-buf.c +++ b/drivers/base/dma-buf.c | |||
| @@ -293,7 +293,7 @@ EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment); | |||
| 293 | * cpu in the kernel context. Calls begin_cpu_access to allow exporter-specific | 293 | * cpu in the kernel context. Calls begin_cpu_access to allow exporter-specific |
| 294 | * preparations. Coherency is only guaranteed in the specified range for the | 294 | * preparations. Coherency is only guaranteed in the specified range for the |
| 295 | * specified access direction. | 295 | * specified access direction. |
| 296 | * @dma_buf: [in] buffer to prepare cpu access for. | 296 | * @dmabuf: [in] buffer to prepare cpu access for. |
| 297 | * @start: [in] start of range for cpu access. | 297 | * @start: [in] start of range for cpu access. |
| 298 | * @len: [in] length of range for cpu access. | 298 | * @len: [in] length of range for cpu access. |
| 299 | * @direction: [in] length of range for cpu access. | 299 | * @direction: [in] length of range for cpu access. |
| @@ -320,7 +320,7 @@ EXPORT_SYMBOL_GPL(dma_buf_begin_cpu_access); | |||
| 320 | * cpu in the kernel context. Calls end_cpu_access to allow exporter-specific | 320 | * cpu in the kernel context. Calls end_cpu_access to allow exporter-specific |
| 321 | * actions. Coherency is only guaranteed in the specified range for the | 321 | * actions. Coherency is only guaranteed in the specified range for the |
| 322 | * specified access direction. | 322 | * specified access direction. |
| 323 | * @dma_buf: [in] buffer to complete cpu access for. | 323 | * @dmabuf: [in] buffer to complete cpu access for. |
| 324 | * @start: [in] start of range for cpu access. | 324 | * @start: [in] start of range for cpu access. |
| 325 | * @len: [in] length of range for cpu access. | 325 | * @len: [in] length of range for cpu access. |
| 326 | * @direction: [in] length of range for cpu access. | 326 | * @direction: [in] length of range for cpu access. |
| @@ -340,7 +340,7 @@ EXPORT_SYMBOL_GPL(dma_buf_end_cpu_access); | |||
| 340 | /** | 340 | /** |
| 341 | * dma_buf_kmap_atomic - Map a page of the buffer object into kernel address | 341 | * dma_buf_kmap_atomic - Map a page of the buffer object into kernel address |
| 342 | * space. The same restrictions as for kmap_atomic and friends apply. | 342 | * space. The same restrictions as for kmap_atomic and friends apply. |
| 343 | * @dma_buf: [in] buffer to map page from. | 343 | * @dmabuf: [in] buffer to map page from. |
| 344 | * @page_num: [in] page in PAGE_SIZE units to map. | 344 | * @page_num: [in] page in PAGE_SIZE units to map. |
| 345 | * | 345 | * |
| 346 | * This call must always succeed, any necessary preparations that might fail | 346 | * This call must always succeed, any necessary preparations that might fail |
| @@ -356,7 +356,7 @@ EXPORT_SYMBOL_GPL(dma_buf_kmap_atomic); | |||
| 356 | 356 | ||
| 357 | /** | 357 | /** |
| 358 | * dma_buf_kunmap_atomic - Unmap a page obtained by dma_buf_kmap_atomic. | 358 | * dma_buf_kunmap_atomic - Unmap a page obtained by dma_buf_kmap_atomic. |
| 359 | * @dma_buf: [in] buffer to unmap page from. | 359 | * @dmabuf: [in] buffer to unmap page from. |
| 360 | * @page_num: [in] page in PAGE_SIZE units to unmap. | 360 | * @page_num: [in] page in PAGE_SIZE units to unmap. |
| 361 | * @vaddr: [in] kernel space pointer obtained from dma_buf_kmap_atomic. | 361 | * @vaddr: [in] kernel space pointer obtained from dma_buf_kmap_atomic. |
| 362 | * | 362 | * |
| @@ -375,7 +375,7 @@ EXPORT_SYMBOL_GPL(dma_buf_kunmap_atomic); | |||
| 375 | /** | 375 | /** |
| 376 | * dma_buf_kmap - Map a page of the buffer object into kernel address space. The | 376 | * dma_buf_kmap - Map a page of the buffer object into kernel address space. The |
| 377 | * same restrictions as for kmap and friends apply. | 377 | * same restrictions as for kmap and friends apply. |
| 378 | * @dma_buf: [in] buffer to map page from. | 378 | * @dmabuf: [in] buffer to map page from. |
| 379 | * @page_num: [in] page in PAGE_SIZE units to map. | 379 | * @page_num: [in] page in PAGE_SIZE units to map. |
| 380 | * | 380 | * |
| 381 | * This call must always succeed, any necessary preparations that might fail | 381 | * This call must always succeed, any necessary preparations that might fail |
| @@ -391,7 +391,7 @@ EXPORT_SYMBOL_GPL(dma_buf_kmap); | |||
| 391 | 391 | ||
| 392 | /** | 392 | /** |
| 393 | * dma_buf_kunmap - Unmap a page obtained by dma_buf_kmap. | 393 | * dma_buf_kunmap - Unmap a page obtained by dma_buf_kmap. |
| 394 | * @dma_buf: [in] buffer to unmap page from. | 394 | * @dmabuf: [in] buffer to unmap page from. |
| 395 | * @page_num: [in] page in PAGE_SIZE units to unmap. | 395 | * @page_num: [in] page in PAGE_SIZE units to unmap. |
| 396 | * @vaddr: [in] kernel space pointer obtained from dma_buf_kmap. | 396 | * @vaddr: [in] kernel space pointer obtained from dma_buf_kmap. |
| 397 | * | 397 | * |
diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 3ec3896c83a6..207c27ddf828 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c | |||
| @@ -80,7 +80,7 @@ struct device *driver_find_device(struct device_driver *drv, | |||
| 80 | struct klist_iter i; | 80 | struct klist_iter i; |
| 81 | struct device *dev; | 81 | struct device *dev; |
| 82 | 82 | ||
| 83 | if (!drv) | 83 | if (!drv || !drv->p) |
| 84 | return NULL; | 84 | return NULL; |
| 85 | 85 | ||
| 86 | klist_iter_init_node(&drv->p->klist_devices, &i, | 86 | klist_iter_init_node(&drv->p->klist_devices, &i, |
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index d6e9d081c8b1..67c3371723cc 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
| @@ -807,44 +807,6 @@ static const struct file_operations oldmem_fops = { | |||
| 807 | }; | 807 | }; |
| 808 | #endif | 808 | #endif |
| 809 | 809 | ||
| 810 | static ssize_t kmsg_writev(struct kiocb *iocb, const struct iovec *iv, | ||
| 811 | unsigned long count, loff_t pos) | ||
| 812 | { | ||
| 813 | char *line, *p; | ||
| 814 | int i; | ||
| 815 | ssize_t ret = -EFAULT; | ||
| 816 | size_t len = iov_length(iv, count); | ||
| 817 | |||
| 818 | line = kmalloc(len + 1, GFP_KERNEL); | ||
| 819 | if (line == NULL) | ||
| 820 | return -ENOMEM; | ||
| 821 | |||
| 822 | /* | ||
| 823 | * copy all vectors into a single string, to ensure we do | ||
| 824 | * not interleave our log line with other printk calls | ||
| 825 | */ | ||
| 826 | p = line; | ||
| 827 | for (i = 0; i < count; i++) { | ||
| 828 | if (copy_from_user(p, iv[i].iov_base, iv[i].iov_len)) | ||
| 829 | goto out; | ||
| 830 | p += iv[i].iov_len; | ||
| 831 | } | ||
| 832 | p[0] = '\0'; | ||
| 833 | |||
| 834 | ret = printk("%s", line); | ||
| 835 | /* printk can add a prefix */ | ||
| 836 | if (ret > len) | ||
| 837 | ret = len; | ||
| 838 | out: | ||
| 839 | kfree(line); | ||
| 840 | return ret; | ||
| 841 | } | ||
| 842 | |||
| 843 | static const struct file_operations kmsg_fops = { | ||
| 844 | .aio_write = kmsg_writev, | ||
| 845 | .llseek = noop_llseek, | ||
| 846 | }; | ||
| 847 | |||
| 848 | static const struct memdev { | 810 | static const struct memdev { |
| 849 | const char *name; | 811 | const char *name; |
| 850 | umode_t mode; | 812 | umode_t mode; |
| @@ -863,7 +825,9 @@ static const struct memdev { | |||
| 863 | [7] = { "full", 0666, &full_fops, NULL }, | 825 | [7] = { "full", 0666, &full_fops, NULL }, |
| 864 | [8] = { "random", 0666, &random_fops, NULL }, | 826 | [8] = { "random", 0666, &random_fops, NULL }, |
| 865 | [9] = { "urandom", 0666, &urandom_fops, NULL }, | 827 | [9] = { "urandom", 0666, &urandom_fops, NULL }, |
| 866 | [11] = { "kmsg", 0, &kmsg_fops, NULL }, | 828 | #ifdef CONFIG_PRINTK |
| 829 | [11] = { "kmsg", 0644, &kmsg_fops, NULL }, | ||
| 830 | #endif | ||
| 867 | #ifdef CONFIG_CRASH_DUMP | 831 | #ifdef CONFIG_CRASH_DUMP |
| 868 | [12] = { "oldmem", 0, &oldmem_fops, NULL }, | 832 | [12] = { "oldmem", 0, &oldmem_fops, NULL }, |
| 869 | #endif | 833 | #endif |
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig new file mode 100644 index 000000000000..29c5cf852efc --- /dev/null +++ b/drivers/extcon/Kconfig | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | menuconfig EXTCON | ||
| 2 | tristate "External Connector Class (extcon) support" | ||
| 3 | help | ||
| 4 | Say Y here to enable external connector class (extcon) support. | ||
| 5 | This allows monitoring external connectors by userspace | ||
| 6 | via sysfs and uevent and supports external connectors with | ||
| 7 | multiple states; i.e., an extcon that may have multiple | ||
| 8 | cables attached. For example, an external connector of a device | ||
| 9 | may be used to connect an HDMI cable and a AC adaptor, and to | ||
| 10 | host USB ports. Many of 30-pin connectors including PDMI are | ||
| 11 | also good examples. | ||
| 12 | |||
| 13 | if EXTCON | ||
| 14 | |||
| 15 | comment "Extcon Device Drivers" | ||
| 16 | |||
| 17 | config EXTCON_GPIO | ||
| 18 | tristate "GPIO extcon support" | ||
| 19 | depends on GENERIC_GPIO | ||
| 20 | help | ||
| 21 | Say Y here to enable GPIO based extcon support. Note that GPIO | ||
| 22 | extcon supports single state per extcon instance. | ||
| 23 | |||
| 24 | config EXTCON_MAX8997 | ||
| 25 | tristate "MAX8997 EXTCON Support" | ||
| 26 | depends on MFD_MAX8997 | ||
| 27 | help | ||
| 28 | If you say yes here you get support for the MUIC device of | ||
| 29 | Maxim MAX8997 PMIC. The MAX8997 MUIC is a USB port accessory | ||
| 30 | detector and switch. | ||
| 31 | |||
| 32 | endif # MULTISTATE_SWITCH | ||
diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile new file mode 100644 index 000000000000..86020bdb6da0 --- /dev/null +++ b/drivers/extcon/Makefile | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | # | ||
| 2 | # Makefile for external connector class (extcon) devices | ||
| 3 | # | ||
| 4 | |||
| 5 | obj-$(CONFIG_EXTCON) += extcon_class.o | ||
| 6 | obj-$(CONFIG_EXTCON_GPIO) += extcon_gpio.o | ||
| 7 | obj-$(CONFIG_EXTCON_MAX8997) += extcon-max8997.o | ||
diff --git a/drivers/misc/max8997-muic.c b/drivers/extcon/extcon-max8997.c index 2e7df9c56491..23416e443765 100644 --- a/drivers/misc/max8997-muic.c +++ b/drivers/extcon/extcon-max8997.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * max8997-muic.c - MAX8997 muic driver for the Maxim 8997 | 2 | * extcon-max8997.c - MAX8997 extcon driver to support MAX8997 MUIC |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2011 Samsung Electrnoics | 4 | * Copyright (C) 2012 Samsung Electrnoics |
| 5 | * Donggeun Kim <dg77.kim@samsung.com> | 5 | * Donggeun Kim <dg77.kim@samsung.com> |
| 6 | * | 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
| @@ -13,11 +13,6 @@ | |||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | * GNU General Public License for more details. | 15 | * GNU General Public License for more details. |
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | * | ||
| 21 | */ | 16 | */ |
| 22 | 17 | ||
| 23 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
| @@ -30,6 +25,9 @@ | |||
| 30 | #include <linux/kobject.h> | 25 | #include <linux/kobject.h> |
| 31 | #include <linux/mfd/max8997.h> | 26 | #include <linux/mfd/max8997.h> |
| 32 | #include <linux/mfd/max8997-private.h> | 27 | #include <linux/mfd/max8997-private.h> |
| 28 | #include <linux/extcon.h> | ||
| 29 | |||
| 30 | #define DEV_NAME "max8997-muic" | ||
| 33 | 31 | ||
| 34 | /* MAX8997-MUIC STATUS1 register */ | 32 | /* MAX8997-MUIC STATUS1 register */ |
| 35 | #define STATUS1_ADC_SHIFT 0 | 33 | #define STATUS1_ADC_SHIFT 0 |
| @@ -95,7 +93,6 @@ static struct max8997_muic_irq muic_irqs[] = { | |||
| 95 | 93 | ||
| 96 | struct max8997_muic_info { | 94 | struct max8997_muic_info { |
| 97 | struct device *dev; | 95 | struct device *dev; |
| 98 | struct max8997_dev *iodev; | ||
| 99 | struct i2c_client *muic; | 96 | struct i2c_client *muic; |
| 100 | struct max8997_muic_platform_data *muic_pdata; | 97 | struct max8997_muic_platform_data *muic_pdata; |
| 101 | 98 | ||
| @@ -106,12 +103,28 @@ struct max8997_muic_info { | |||
| 106 | int pre_adc; | 103 | int pre_adc; |
| 107 | 104 | ||
| 108 | struct mutex mutex; | 105 | struct mutex mutex; |
| 106 | |||
| 107 | struct extcon_dev *edev; | ||
| 108 | }; | ||
| 109 | |||
| 110 | const char *max8997_extcon_cable[] = { | ||
| 111 | [0] = "USB", | ||
| 112 | [1] = "USB-Host", | ||
| 113 | [2] = "TA", | ||
| 114 | [3] = "Fast-charger", | ||
| 115 | [4] = "Slow-charger", | ||
| 116 | [5] = "Charge-downstream", | ||
| 117 | [6] = "MHL", | ||
| 118 | [7] = "Dock-desk", | ||
| 119 | [7] = "Dock-card", | ||
| 120 | [8] = "JIG", | ||
| 121 | |||
| 122 | NULL, | ||
| 109 | }; | 123 | }; |
| 110 | 124 | ||
| 111 | static int max8997_muic_handle_usb(struct max8997_muic_info *info, | 125 | static int max8997_muic_handle_usb(struct max8997_muic_info *info, |
| 112 | enum max8997_muic_usb_type usb_type, bool attached) | 126 | enum max8997_muic_usb_type usb_type, bool attached) |
| 113 | { | 127 | { |
| 114 | struct max8997_muic_platform_data *mdata = info->muic_pdata; | ||
| 115 | int ret = 0; | 128 | int ret = 0; |
| 116 | 129 | ||
| 117 | if (usb_type == MAX8997_USB_HOST) { | 130 | if (usb_type == MAX8997_USB_HOST) { |
| @@ -125,25 +138,25 @@ static int max8997_muic_handle_usb(struct max8997_muic_info *info, | |||
| 125 | } | 138 | } |
| 126 | } | 139 | } |
| 127 | 140 | ||
| 128 | if (mdata->usb_callback) | 141 | switch (usb_type) { |
| 129 | mdata->usb_callback(usb_type, attached); | 142 | case MAX8997_USB_HOST: |
| 143 | extcon_set_cable_state(info->edev, "USB-Host", attached); | ||
| 144 | break; | ||
| 145 | case MAX8997_USB_DEVICE: | ||
| 146 | extcon_set_cable_state(info->edev, "USB", attached); | ||
| 147 | break; | ||
| 148 | default: | ||
| 149 | ret = -EINVAL; | ||
| 150 | break; | ||
| 151 | } | ||
| 152 | |||
| 130 | out: | 153 | out: |
| 131 | return ret; | 154 | return ret; |
| 132 | } | 155 | } |
| 133 | 156 | ||
| 134 | static void max8997_muic_handle_mhl(struct max8997_muic_info *info, | ||
| 135 | bool attached) | ||
| 136 | { | ||
| 137 | struct max8997_muic_platform_data *mdata = info->muic_pdata; | ||
| 138 | |||
| 139 | if (mdata->mhl_callback) | ||
| 140 | mdata->mhl_callback(attached); | ||
| 141 | } | ||
| 142 | |||
| 143 | static int max8997_muic_handle_dock(struct max8997_muic_info *info, | 157 | static int max8997_muic_handle_dock(struct max8997_muic_info *info, |
| 144 | int adc, bool attached) | 158 | int adc, bool attached) |
| 145 | { | 159 | { |
| 146 | struct max8997_muic_platform_data *mdata = info->muic_pdata; | ||
| 147 | int ret = 0; | 160 | int ret = 0; |
| 148 | 161 | ||
| 149 | /* switch to AUDIO */ | 162 | /* switch to AUDIO */ |
| @@ -157,14 +170,13 @@ static int max8997_muic_handle_dock(struct max8997_muic_info *info, | |||
| 157 | 170 | ||
| 158 | switch (adc) { | 171 | switch (adc) { |
| 159 | case MAX8997_ADC_DESKDOCK: | 172 | case MAX8997_ADC_DESKDOCK: |
| 160 | if (mdata->deskdock_callback) | 173 | extcon_set_cable_state(info->edev, "Dock-desk", attached); |
| 161 | mdata->deskdock_callback(attached); | ||
| 162 | break; | 174 | break; |
| 163 | case MAX8997_ADC_CARDOCK: | 175 | case MAX8997_ADC_CARDOCK: |
| 164 | if (mdata->cardock_callback) | 176 | extcon_set_cable_state(info->edev, "Dock-card", attached); |
| 165 | mdata->cardock_callback(attached); | ||
| 166 | break; | 177 | break; |
| 167 | default: | 178 | default: |
| 179 | ret = -EINVAL; | ||
| 168 | break; | 180 | break; |
| 169 | } | 181 | } |
| 170 | out: | 182 | out: |
| @@ -174,7 +186,6 @@ out: | |||
| 174 | static int max8997_muic_handle_jig_uart(struct max8997_muic_info *info, | 186 | static int max8997_muic_handle_jig_uart(struct max8997_muic_info *info, |
| 175 | bool attached) | 187 | bool attached) |
| 176 | { | 188 | { |
| 177 | struct max8997_muic_platform_data *mdata = info->muic_pdata; | ||
| 178 | int ret = 0; | 189 | int ret = 0; |
| 179 | 190 | ||
| 180 | /* switch to UART */ | 191 | /* switch to UART */ |
| @@ -186,8 +197,7 @@ static int max8997_muic_handle_jig_uart(struct max8997_muic_info *info, | |||
| 186 | goto out; | 197 | goto out; |
| 187 | } | 198 | } |
| 188 | 199 | ||
| 189 | if (mdata->uart_callback) | 200 | extcon_set_cable_state(info->edev, "JIG", attached); |
| 190 | mdata->uart_callback(attached); | ||
| 191 | out: | 201 | out: |
| 192 | return ret; | 202 | return ret; |
| 193 | } | 203 | } |
| @@ -201,7 +211,7 @@ static int max8997_muic_handle_adc_detach(struct max8997_muic_info *info) | |||
| 201 | ret = max8997_muic_handle_usb(info, MAX8997_USB_HOST, false); | 211 | ret = max8997_muic_handle_usb(info, MAX8997_USB_HOST, false); |
| 202 | break; | 212 | break; |
| 203 | case MAX8997_ADC_MHL: | 213 | case MAX8997_ADC_MHL: |
| 204 | max8997_muic_handle_mhl(info, false); | 214 | extcon_set_cable_state(info->edev, "MHL", false); |
| 205 | break; | 215 | break; |
| 206 | case MAX8997_ADC_JIG_USB_1: | 216 | case MAX8997_ADC_JIG_USB_1: |
| 207 | case MAX8997_ADC_JIG_USB_2: | 217 | case MAX8997_ADC_JIG_USB_2: |
| @@ -230,7 +240,7 @@ static int max8997_muic_handle_adc(struct max8997_muic_info *info, int adc) | |||
| 230 | ret = max8997_muic_handle_usb(info, MAX8997_USB_HOST, true); | 240 | ret = max8997_muic_handle_usb(info, MAX8997_USB_HOST, true); |
| 231 | break; | 241 | break; |
| 232 | case MAX8997_ADC_MHL: | 242 | case MAX8997_ADC_MHL: |
| 233 | max8997_muic_handle_mhl(info, true); | 243 | extcon_set_cable_state(info->edev, "MHL", true); |
| 234 | break; | 244 | break; |
| 235 | case MAX8997_ADC_JIG_USB_1: | 245 | case MAX8997_ADC_JIG_USB_1: |
| 236 | case MAX8997_ADC_JIG_USB_2: | 246 | case MAX8997_ADC_JIG_USB_2: |
| @@ -247,10 +257,40 @@ static int max8997_muic_handle_adc(struct max8997_muic_info *info, int adc) | |||
| 247 | ret = max8997_muic_handle_adc_detach(info); | 257 | ret = max8997_muic_handle_adc_detach(info); |
| 248 | break; | 258 | break; |
| 249 | default: | 259 | default: |
| 250 | break; | 260 | ret = -EINVAL; |
| 261 | goto out; | ||
| 251 | } | 262 | } |
| 252 | 263 | ||
| 253 | info->pre_adc = adc; | 264 | info->pre_adc = adc; |
| 265 | out: | ||
| 266 | return ret; | ||
| 267 | } | ||
| 268 | |||
| 269 | static int max8997_muic_handle_charger_type_detach( | ||
| 270 | struct max8997_muic_info *info) | ||
| 271 | { | ||
| 272 | int ret = 0; | ||
| 273 | |||
| 274 | switch (info->pre_charger_type) { | ||
| 275 | case MAX8997_CHARGER_TYPE_USB: | ||
| 276 | extcon_set_cable_state(info->edev, "USB", false); | ||
| 277 | break; | ||
| 278 | case MAX8997_CHARGER_TYPE_DOWNSTREAM_PORT: | ||
| 279 | extcon_set_cable_state(info->edev, "Charge-downstream", false); | ||
| 280 | break; | ||
| 281 | case MAX8997_CHARGER_TYPE_DEDICATED_CHG: | ||
| 282 | extcon_set_cable_state(info->edev, "TA", false); | ||
| 283 | break; | ||
| 284 | case MAX8997_CHARGER_TYPE_500MA: | ||
| 285 | extcon_set_cable_state(info->edev, "Slow-charger", false); | ||
| 286 | break; | ||
| 287 | case MAX8997_CHARGER_TYPE_1A: | ||
| 288 | extcon_set_cable_state(info->edev, "Fast-charger", false); | ||
| 289 | break; | ||
| 290 | default: | ||
| 291 | ret = -EINVAL; | ||
| 292 | break; | ||
| 293 | } | ||
| 254 | 294 | ||
| 255 | return ret; | 295 | return ret; |
| 256 | } | 296 | } |
| @@ -258,7 +298,6 @@ static int max8997_muic_handle_adc(struct max8997_muic_info *info, int adc) | |||
| 258 | static int max8997_muic_handle_charger_type(struct max8997_muic_info *info, | 298 | static int max8997_muic_handle_charger_type(struct max8997_muic_info *info, |
| 259 | enum max8997_muic_charger_type charger_type) | 299 | enum max8997_muic_charger_type charger_type) |
| 260 | { | 300 | { |
| 261 | struct max8997_muic_platform_data *mdata = info->muic_pdata; | ||
| 262 | u8 adc; | 301 | u8 adc; |
| 263 | int ret; | 302 | int ret; |
| 264 | 303 | ||
| @@ -270,30 +309,29 @@ static int max8997_muic_handle_charger_type(struct max8997_muic_info *info, | |||
| 270 | 309 | ||
| 271 | switch (charger_type) { | 310 | switch (charger_type) { |
| 272 | case MAX8997_CHARGER_TYPE_NONE: | 311 | case MAX8997_CHARGER_TYPE_NONE: |
| 273 | if (mdata->charger_callback) | 312 | ret = max8997_muic_handle_charger_type_detach(info); |
| 274 | mdata->charger_callback(false, charger_type); | ||
| 275 | if (info->pre_charger_type == MAX8997_CHARGER_TYPE_USB) { | ||
| 276 | max8997_muic_handle_usb(info, | ||
| 277 | MAX8997_USB_DEVICE, false); | ||
| 278 | } | ||
| 279 | break; | 313 | break; |
| 280 | case MAX8997_CHARGER_TYPE_USB: | 314 | case MAX8997_CHARGER_TYPE_USB: |
| 281 | if ((adc & STATUS1_ADC_MASK) == MAX8997_ADC_OPEN) { | 315 | if ((adc & STATUS1_ADC_MASK) == MAX8997_ADC_OPEN) { |
| 282 | max8997_muic_handle_usb(info, | 316 | max8997_muic_handle_usb(info, |
| 283 | MAX8997_USB_DEVICE, true); | 317 | MAX8997_USB_DEVICE, true); |
| 284 | } | 318 | } |
| 285 | if (mdata->charger_callback) | ||
| 286 | mdata->charger_callback(true, charger_type); | ||
| 287 | break; | 319 | break; |
| 288 | case MAX8997_CHARGER_TYPE_DOWNSTREAM_PORT: | 320 | case MAX8997_CHARGER_TYPE_DOWNSTREAM_PORT: |
| 321 | extcon_set_cable_state(info->edev, "Charge-downstream", true); | ||
| 322 | break; | ||
| 289 | case MAX8997_CHARGER_TYPE_DEDICATED_CHG: | 323 | case MAX8997_CHARGER_TYPE_DEDICATED_CHG: |
| 324 | extcon_set_cable_state(info->edev, "TA", true); | ||
| 325 | break; | ||
| 290 | case MAX8997_CHARGER_TYPE_500MA: | 326 | case MAX8997_CHARGER_TYPE_500MA: |
| 327 | extcon_set_cable_state(info->edev, "Slow-charger", true); | ||
| 328 | break; | ||
| 291 | case MAX8997_CHARGER_TYPE_1A: | 329 | case MAX8997_CHARGER_TYPE_1A: |
| 292 | if (mdata->charger_callback) | 330 | extcon_set_cable_state(info->edev, "Fast-charger", true); |
| 293 | mdata->charger_callback(true, charger_type); | ||
| 294 | break; | 331 | break; |
| 295 | default: | 332 | default: |
| 296 | break; | 333 | ret = -EINVAL; |
| 334 | goto out; | ||
| 297 | } | 335 | } |
| 298 | 336 | ||
| 299 | info->pre_charger_type = charger_type; | 337 | info->pre_charger_type = charger_type; |
| @@ -305,18 +343,17 @@ static void max8997_muic_irq_work(struct work_struct *work) | |||
| 305 | { | 343 | { |
| 306 | struct max8997_muic_info *info = container_of(work, | 344 | struct max8997_muic_info *info = container_of(work, |
| 307 | struct max8997_muic_info, irq_work); | 345 | struct max8997_muic_info, irq_work); |
| 308 | struct max8997_platform_data *pdata = | 346 | struct max8997_dev *max8997 = i2c_get_clientdata(info->muic); |
| 309 | dev_get_platdata(info->iodev->dev); | 347 | u8 status[2]; |
| 310 | u8 status[3]; | ||
| 311 | u8 adc, chg_type; | 348 | u8 adc, chg_type; |
| 312 | 349 | ||
| 313 | int irq_type = info->irq - pdata->irq_base; | 350 | int irq_type = info->irq - max8997->irq_base; |
| 314 | int ret; | 351 | int ret; |
| 315 | 352 | ||
| 316 | mutex_lock(&info->mutex); | 353 | mutex_lock(&info->mutex); |
| 317 | 354 | ||
| 318 | ret = max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1, | 355 | ret = max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1, |
| 319 | 3, status); | 356 | 2, status); |
| 320 | if (ret) { | 357 | if (ret) { |
| 321 | dev_err(info->dev, "failed to read muic register\n"); | 358 | dev_err(info->dev, "failed to read muic register\n"); |
| 322 | mutex_unlock(&info->mutex); | 359 | mutex_unlock(&info->mutex); |
| @@ -340,8 +377,8 @@ static void max8997_muic_irq_work(struct work_struct *work) | |||
| 340 | max8997_muic_handle_charger_type(info, chg_type); | 377 | max8997_muic_handle_charger_type(info, chg_type); |
| 341 | break; | 378 | break; |
| 342 | default: | 379 | default: |
| 343 | dev_info(info->dev, "misc interrupt: %s occurred\n", | 380 | dev_info(info->dev, "misc interrupt: irq %d occurred\n", |
| 344 | muic_irqs[irq_type].name); | 381 | irq_type); |
| 345 | break; | 382 | break; |
| 346 | } | 383 | } |
| 347 | 384 | ||
| @@ -387,21 +424,10 @@ static void max8997_muic_detect_dev(struct max8997_muic_info *info) | |||
| 387 | max8997_muic_handle_charger_type(info, chg_type); | 424 | max8997_muic_handle_charger_type(info, chg_type); |
| 388 | } | 425 | } |
| 389 | 426 | ||
| 390 | static void max8997_initialize_device(struct max8997_muic_info *info) | ||
| 391 | { | ||
| 392 | struct max8997_muic_platform_data *mdata = info->muic_pdata; | ||
| 393 | int i; | ||
| 394 | |||
| 395 | for (i = 0; i < mdata->num_init_data; i++) { | ||
| 396 | max8997_write_reg(info->muic, mdata->init_data[i].addr, | ||
| 397 | mdata->init_data[i].data); | ||
| 398 | } | ||
| 399 | } | ||
| 400 | |||
| 401 | static int __devinit max8997_muic_probe(struct platform_device *pdev) | 427 | static int __devinit max8997_muic_probe(struct platform_device *pdev) |
| 402 | { | 428 | { |
| 403 | struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent); | 429 | struct max8997_dev *max8997 = dev_get_drvdata(pdev->dev.parent); |
| 404 | struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev); | 430 | struct max8997_platform_data *pdata = dev_get_platdata(max8997->dev); |
| 405 | struct max8997_muic_info *info; | 431 | struct max8997_muic_info *info; |
| 406 | int ret, i; | 432 | int ret, i; |
| 407 | 433 | ||
| @@ -412,16 +438,8 @@ static int __devinit max8997_muic_probe(struct platform_device *pdev) | |||
| 412 | goto err_kfree; | 438 | goto err_kfree; |
| 413 | } | 439 | } |
| 414 | 440 | ||
| 415 | if (!pdata->muic_pdata) { | ||
| 416 | dev_err(&pdev->dev, "failed to get platform_data\n"); | ||
| 417 | ret = -EINVAL; | ||
| 418 | goto err_pdata; | ||
| 419 | } | ||
| 420 | info->muic_pdata = pdata->muic_pdata; | ||
| 421 | |||
| 422 | info->dev = &pdev->dev; | 441 | info->dev = &pdev->dev; |
| 423 | info->iodev = iodev; | 442 | info->muic = max8997->muic; |
| 424 | info->muic = iodev->muic; | ||
| 425 | 443 | ||
| 426 | platform_set_drvdata(pdev, info); | 444 | platform_set_drvdata(pdev, info); |
| 427 | mutex_init(&info->mutex); | 445 | mutex_init(&info->mutex); |
| @@ -444,18 +462,41 @@ static int __devinit max8997_muic_probe(struct platform_device *pdev) | |||
| 444 | } | 462 | } |
| 445 | } | 463 | } |
| 446 | 464 | ||
| 465 | /* External connector */ | ||
| 466 | info->edev = kzalloc(sizeof(struct extcon_dev), GFP_KERNEL); | ||
| 467 | if (!info->edev) { | ||
| 468 | dev_err(&pdev->dev, "failed to allocate memory for extcon\n"); | ||
| 469 | ret = -ENOMEM; | ||
| 470 | goto err_irq; | ||
| 471 | } | ||
| 472 | info->edev->name = DEV_NAME; | ||
| 473 | info->edev->supported_cable = max8997_extcon_cable; | ||
| 474 | ret = extcon_dev_register(info->edev, NULL); | ||
| 475 | if (ret) { | ||
| 476 | dev_err(&pdev->dev, "failed to register extcon device\n"); | ||
| 477 | goto err_extcon; | ||
| 478 | } | ||
| 479 | |||
| 447 | /* Initialize registers according to platform data */ | 480 | /* Initialize registers according to platform data */ |
| 448 | max8997_initialize_device(info); | 481 | if (pdata->muic_pdata) { |
| 482 | struct max8997_muic_platform_data *mdata = info->muic_pdata; | ||
| 483 | |||
| 484 | for (i = 0; i < mdata->num_init_data; i++) { | ||
| 485 | max8997_write_reg(info->muic, mdata->init_data[i].addr, | ||
| 486 | mdata->init_data[i].data); | ||
| 487 | } | ||
| 488 | } | ||
| 449 | 489 | ||
| 450 | /* Initial device detection */ | 490 | /* Initial device detection */ |
| 451 | max8997_muic_detect_dev(info); | 491 | max8997_muic_detect_dev(info); |
| 452 | 492 | ||
| 453 | return ret; | 493 | return ret; |
| 454 | 494 | ||
| 495 | err_extcon: | ||
| 496 | kfree(info->edev); | ||
| 455 | err_irq: | 497 | err_irq: |
| 456 | while (--i >= 0) | 498 | while (--i >= 0) |
| 457 | free_irq(pdata->irq_base + muic_irqs[i].irq, info); | 499 | free_irq(pdata->irq_base + muic_irqs[i].irq, info); |
| 458 | err_pdata: | ||
| 459 | kfree(info); | 500 | kfree(info); |
| 460 | err_kfree: | 501 | err_kfree: |
| 461 | return ret; | 502 | return ret; |
| @@ -464,14 +505,15 @@ err_kfree: | |||
| 464 | static int __devexit max8997_muic_remove(struct platform_device *pdev) | 505 | static int __devexit max8997_muic_remove(struct platform_device *pdev) |
| 465 | { | 506 | { |
| 466 | struct max8997_muic_info *info = platform_get_drvdata(pdev); | 507 | struct max8997_muic_info *info = platform_get_drvdata(pdev); |
| 467 | struct max8997_platform_data *pdata = | 508 | struct max8997_dev *max8997 = i2c_get_clientdata(info->muic); |
| 468 | dev_get_platdata(info->iodev->dev); | ||
| 469 | int i; | 509 | int i; |
| 470 | 510 | ||
| 471 | for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) | 511 | for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) |
| 472 | free_irq(pdata->irq_base + muic_irqs[i].irq, info); | 512 | free_irq(max8997->irq_base + muic_irqs[i].irq, info); |
| 473 | cancel_work_sync(&info->irq_work); | 513 | cancel_work_sync(&info->irq_work); |
| 474 | 514 | ||
| 515 | extcon_dev_unregister(info->edev); | ||
| 516 | |||
| 475 | kfree(info); | 517 | kfree(info); |
| 476 | 518 | ||
| 477 | return 0; | 519 | return 0; |
| @@ -479,7 +521,7 @@ static int __devexit max8997_muic_remove(struct platform_device *pdev) | |||
| 479 | 521 | ||
| 480 | static struct platform_driver max8997_muic_driver = { | 522 | static struct platform_driver max8997_muic_driver = { |
| 481 | .driver = { | 523 | .driver = { |
| 482 | .name = "max8997-muic", | 524 | .name = DEV_NAME, |
| 483 | .owner = THIS_MODULE, | 525 | .owner = THIS_MODULE, |
| 484 | }, | 526 | }, |
| 485 | .probe = max8997_muic_probe, | 527 | .probe = max8997_muic_probe, |
| @@ -488,6 +530,6 @@ static struct platform_driver max8997_muic_driver = { | |||
| 488 | 530 | ||
| 489 | module_platform_driver(max8997_muic_driver); | 531 | module_platform_driver(max8997_muic_driver); |
| 490 | 532 | ||
| 491 | MODULE_DESCRIPTION("Maxim MAX8997 MUIC driver"); | 533 | MODULE_DESCRIPTION("Maxim MAX8997 Extcon driver"); |
| 492 | MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>"); | 534 | MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>"); |
| 493 | MODULE_LICENSE("GPL"); | 535 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/extcon/extcon_class.c b/drivers/extcon/extcon_class.c new file mode 100644 index 000000000000..f598a700ec15 --- /dev/null +++ b/drivers/extcon/extcon_class.c | |||
| @@ -0,0 +1,832 @@ | |||
| 1 | /* | ||
| 2 | * drivers/extcon/extcon_class.c | ||
| 3 | * | ||
| 4 | * External connector (extcon) class driver | ||
| 5 | * | ||
| 6 | * Copyright (C) 2012 Samsung Electronics | ||
| 7 | * Author: Donggeun Kim <dg77.kim@samsung.com> | ||
| 8 | * Author: MyungJoo Ham <myungjoo.ham@samsung.com> | ||
| 9 | * | ||
| 10 | * based on android/drivers/switch/switch_class.c | ||
| 11 | * Copyright (C) 2008 Google, Inc. | ||
| 12 | * Author: Mike Lockwood <lockwood@android.com> | ||
| 13 | * | ||
| 14 | * This software is licensed under the terms of the GNU General Public | ||
| 15 | * License version 2, as published by the Free Software Foundation, and | ||
| 16 | * may be copied, distributed, and modified under those terms. | ||
| 17 | * | ||
| 18 | * This program is distributed in the hope that it will be useful, | ||
| 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 21 | * GNU General Public License for more details. | ||
| 22 | * | ||
| 23 | */ | ||
| 24 | |||
| 25 | #include <linux/module.h> | ||
| 26 | #include <linux/types.h> | ||
| 27 | #include <linux/init.h> | ||
| 28 | #include <linux/device.h> | ||
| 29 | #include <linux/fs.h> | ||
| 30 | #include <linux/err.h> | ||
| 31 | #include <linux/extcon.h> | ||
| 32 | #include <linux/slab.h> | ||
| 33 | |||
| 34 | /* | ||
| 35 | * extcon_cable_name suggests the standard cable names for commonly used | ||
| 36 | * cable types. | ||
| 37 | * | ||
| 38 | * However, please do not use extcon_cable_name directly for extcon_dev | ||
| 39 | * struct's supported_cable pointer unless your device really supports | ||
| 40 | * every single port-type of the following cable names. Please choose cable | ||
| 41 | * names that are actually used in your extcon device. | ||
| 42 | */ | ||
| 43 | const char *extcon_cable_name[] = { | ||
| 44 | [EXTCON_USB] = "USB", | ||
| 45 | [EXTCON_USB_HOST] = "USB-Host", | ||
| 46 | [EXTCON_TA] = "TA", | ||
| 47 | [EXTCON_FAST_CHARGER] = "Fast-charger", | ||
| 48 | [EXTCON_SLOW_CHARGER] = "Slow-charger", | ||
| 49 | [EXTCON_CHARGE_DOWNSTREAM] = "Charge-downstream", | ||
| 50 | [EXTCON_HDMI] = "HDMI", | ||
| 51 | [EXTCON_MHL] = "MHL", | ||
| 52 | [EXTCON_DVI] = "DVI", | ||
| 53 | [EXTCON_VGA] = "VGA", | ||
| 54 | [EXTCON_DOCK] = "Dock", | ||
| 55 | [EXTCON_LINE_IN] = "Line-in", | ||
| 56 | [EXTCON_LINE_OUT] = "Line-out", | ||
| 57 | [EXTCON_MIC_IN] = "Microphone", | ||
| 58 | [EXTCON_HEADPHONE_OUT] = "Headphone", | ||
| 59 | [EXTCON_SPDIF_IN] = "SPDIF-in", | ||
| 60 | [EXTCON_SPDIF_OUT] = "SPDIF-out", | ||
| 61 | [EXTCON_VIDEO_IN] = "Video-in", | ||
| 62 | [EXTCON_VIDEO_OUT] = "Video-out", | ||
| 63 | [EXTCON_MECHANICAL] = "Mechanical", | ||
| 64 | |||
| 65 | NULL, | ||
| 66 | }; | ||
| 67 | |||
| 68 | struct class *extcon_class; | ||
| 69 | #if defined(CONFIG_ANDROID) | ||
| 70 | static struct class_compat *switch_class; | ||
| 71 | #endif /* CONFIG_ANDROID */ | ||
| 72 | |||
| 73 | static LIST_HEAD(extcon_dev_list); | ||
| 74 | static DEFINE_MUTEX(extcon_dev_list_lock); | ||
| 75 | |||
| 76 | /** | ||
| 77 | * check_mutually_exclusive - Check if new_state violates mutually_exclusive | ||
| 78 | * condition. | ||
| 79 | * @edev: the extcon device | ||
| 80 | * @new_state: new cable attach status for @edev | ||
| 81 | * | ||
| 82 | * Returns 0 if nothing violates. Returns the index + 1 for the first | ||
| 83 | * violated condition. | ||
| 84 | */ | ||
| 85 | static int check_mutually_exclusive(struct extcon_dev *edev, u32 new_state) | ||
| 86 | { | ||
| 87 | int i = 0; | ||
| 88 | |||
| 89 | if (!edev->mutually_exclusive) | ||
| 90 | return 0; | ||
| 91 | |||
| 92 | for (i = 0; edev->mutually_exclusive[i]; i++) { | ||
| 93 | int count = 0, j; | ||
| 94 | u32 correspondants = new_state & edev->mutually_exclusive[i]; | ||
| 95 | u32 exp = 1; | ||
| 96 | |||
| 97 | for (j = 0; j < 32; j++) { | ||
| 98 | if (exp & correspondants) | ||
| 99 | count++; | ||
| 100 | if (count > 1) | ||
| 101 | return i + 1; | ||
| 102 | exp <<= 1; | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 106 | return 0; | ||
| 107 | } | ||
| 108 | |||
| 109 | static ssize_t state_show(struct device *dev, struct device_attribute *attr, | ||
| 110 | char *buf) | ||
| 111 | { | ||
| 112 | int i, count = 0; | ||
| 113 | struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev); | ||
| 114 | |||
| 115 | if (edev->print_state) { | ||
| 116 | int ret = edev->print_state(edev, buf); | ||
| 117 | |||
| 118 | if (ret >= 0) | ||
| 119 | return ret; | ||
| 120 | /* Use default if failed */ | ||
| 121 | } | ||
| 122 | |||
| 123 | if (edev->max_supported == 0) | ||
| 124 | return sprintf(buf, "%u\n", edev->state); | ||
| 125 | |||
| 126 | for (i = 0; i < SUPPORTED_CABLE_MAX; i++) { | ||
| 127 | if (!edev->supported_cable[i]) | ||
| 128 | break; | ||
| 129 | count += sprintf(buf + count, "%s=%d\n", | ||
| 130 | edev->supported_cable[i], | ||
| 131 | !!(edev->state & (1 << i))); | ||
| 132 | } | ||
| 133 | |||
| 134 | return count; | ||
| 135 | } | ||
| 136 | |||
| 137 | int extcon_set_state(struct extcon_dev *edev, u32 state); | ||
| 138 | static ssize_t state_store(struct device *dev, struct device_attribute *attr, | ||
| 139 | const char *buf, size_t count) | ||
| 140 | { | ||
| 141 | u32 state; | ||
| 142 | ssize_t ret = 0; | ||
| 143 | struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev); | ||
| 144 | |||
| 145 | ret = sscanf(buf, "0x%x", &state); | ||
| 146 | if (ret == 0) | ||
| 147 | ret = -EINVAL; | ||
| 148 | else | ||
| 149 | ret = extcon_set_state(edev, state); | ||
| 150 | |||
| 151 | if (ret < 0) | ||
| 152 | return ret; | ||
| 153 | |||
| 154 | return count; | ||
| 155 | } | ||
| 156 | |||
| 157 | static ssize_t name_show(struct device *dev, struct device_attribute *attr, | ||
| 158 | char *buf) | ||
| 159 | { | ||
| 160 | struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev); | ||
| 161 | |||
| 162 | /* Optional callback given by the user */ | ||
| 163 | if (edev->print_name) { | ||
| 164 | int ret = edev->print_name(edev, buf); | ||
| 165 | if (ret >= 0) | ||
| 166 | return ret; | ||
| 167 | } | ||
| 168 | |||
| 169 | return sprintf(buf, "%s\n", dev_name(edev->dev)); | ||
| 170 | } | ||
| 171 | |||
| 172 | static ssize_t cable_name_show(struct device *dev, | ||
| 173 | struct device_attribute *attr, char *buf) | ||
| 174 | { | ||
| 175 | struct extcon_cable *cable = container_of(attr, struct extcon_cable, | ||
| 176 | attr_name); | ||
| 177 | |||
| 178 | return sprintf(buf, "%s\n", | ||
| 179 | cable->edev->supported_cable[cable->cable_index]); | ||
| 180 | } | ||
| 181 | |||
| 182 | static ssize_t cable_state_show(struct device *dev, | ||
| 183 | struct device_attribute *attr, char *buf) | ||
| 184 | { | ||
| 185 | struct extcon_cable *cable = container_of(attr, struct extcon_cable, | ||
| 186 | attr_state); | ||
| 187 | |||
| 188 | return sprintf(buf, "%d\n", | ||
| 189 | extcon_get_cable_state_(cable->edev, | ||
| 190 | cable->cable_index)); | ||
| 191 | } | ||
| 192 | |||
| 193 | static ssize_t cable_state_store(struct device *dev, | ||
| 194 | struct device_attribute *attr, const char *buf, | ||
| 195 | size_t count) | ||
| 196 | { | ||
| 197 | struct extcon_cable *cable = container_of(attr, struct extcon_cable, | ||
| 198 | attr_state); | ||
| 199 | int ret, state; | ||
| 200 | |||
| 201 | ret = sscanf(buf, "%d", &state); | ||
| 202 | if (ret == 0) | ||
| 203 | ret = -EINVAL; | ||
| 204 | else | ||
| 205 | ret = extcon_set_cable_state_(cable->edev, cable->cable_index, | ||
| 206 | state); | ||
| 207 | |||
| 208 | if (ret < 0) | ||
| 209 | return ret; | ||
| 210 | return count; | ||
| 211 | } | ||
| 212 | |||
| 213 | /** | ||
| 214 | * extcon_update_state() - Update the cable attach states of the extcon device | ||
| 215 | * only for the masked bits. | ||
| 216 | * @edev: the extcon device | ||
| 217 | * @mask: the bit mask to designate updated bits. | ||
| 218 | * @state: new cable attach status for @edev | ||
| 219 | * | ||
| 220 | * Changing the state sends uevent with environment variable containing | ||
| 221 | * the name of extcon device (envp[0]) and the state output (envp[1]). | ||
| 222 | * Tizen uses this format for extcon device to get events from ports. | ||
| 223 | * Android uses this format as well. | ||
| 224 | * | ||
| 225 | * Note that the notifier provides which bits are changed in the state | ||
| 226 | * variable with the val parameter (second) to the callback. | ||
| 227 | */ | ||
| 228 | int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state) | ||
| 229 | { | ||
| 230 | char name_buf[120]; | ||
| 231 | char state_buf[120]; | ||
| 232 | char *prop_buf; | ||
| 233 | char *envp[3]; | ||
| 234 | int env_offset = 0; | ||
| 235 | int length; | ||
| 236 | unsigned long flags; | ||
| 237 | |||
| 238 | spin_lock_irqsave(&edev->lock, flags); | ||
| 239 | |||
| 240 | if (edev->state != ((edev->state & ~mask) | (state & mask))) { | ||
| 241 | u32 old_state = edev->state; | ||
| 242 | |||
| 243 | if (check_mutually_exclusive(edev, (edev->state & ~mask) | | ||
| 244 | (state & mask))) { | ||
| 245 | spin_unlock_irqrestore(&edev->lock, flags); | ||
| 246 | return -EPERM; | ||
| 247 | } | ||
| 248 | |||
| 249 | edev->state &= ~mask; | ||
| 250 | edev->state |= state & mask; | ||
| 251 | |||
| 252 | raw_notifier_call_chain(&edev->nh, old_state, edev); | ||
| 253 | |||
| 254 | /* This could be in interrupt handler */ | ||
| 255 | prop_buf = (char *)get_zeroed_page(GFP_ATOMIC); | ||
| 256 | if (prop_buf) { | ||
| 257 | length = name_show(edev->dev, NULL, prop_buf); | ||
| 258 | if (length > 0) { | ||
| 259 | if (prop_buf[length - 1] == '\n') | ||
| 260 | prop_buf[length - 1] = 0; | ||
| 261 | snprintf(name_buf, sizeof(name_buf), | ||
| 262 | "NAME=%s", prop_buf); | ||
| 263 | envp[env_offset++] = name_buf; | ||
| 264 | } | ||
| 265 | length = state_show(edev->dev, NULL, prop_buf); | ||
| 266 | if (length > 0) { | ||
| 267 | if (prop_buf[length - 1] == '\n') | ||
| 268 | prop_buf[length - 1] = 0; | ||
| 269 | snprintf(state_buf, sizeof(state_buf), | ||
| 270 | "STATE=%s", prop_buf); | ||
| 271 | envp[env_offset++] = state_buf; | ||
| 272 | } | ||
| 273 | envp[env_offset] = NULL; | ||
| 274 | /* Unlock early before uevent */ | ||
| 275 | spin_unlock_irqrestore(&edev->lock, flags); | ||
| 276 | |||
| 277 | kobject_uevent_env(&edev->dev->kobj, KOBJ_CHANGE, envp); | ||
| 278 | free_page((unsigned long)prop_buf); | ||
| 279 | } else { | ||
| 280 | /* Unlock early before uevent */ | ||
| 281 | spin_unlock_irqrestore(&edev->lock, flags); | ||
| 282 | |||
| 283 | dev_err(edev->dev, "out of memory in extcon_set_state\n"); | ||
| 284 | kobject_uevent(&edev->dev->kobj, KOBJ_CHANGE); | ||
| 285 | } | ||
| 286 | } else { | ||
| 287 | /* No changes */ | ||
| 288 | spin_unlock_irqrestore(&edev->lock, flags); | ||
| 289 | } | ||
| 290 | |||
| 291 | return 0; | ||
| 292 | } | ||
| 293 | EXPORT_SYMBOL_GPL(extcon_update_state); | ||
| 294 | |||
| 295 | /** | ||
| 296 | * extcon_set_state() - Set the cable attach states of the extcon device. | ||
| 297 | * @edev: the extcon device | ||
| 298 | * @state: new cable attach status for @edev | ||
| 299 | * | ||
| 300 | * Note that notifier provides which bits are changed in the state | ||
| 301 | * variable with the val parameter (second) to the callback. | ||
| 302 | */ | ||
| 303 | int extcon_set_state(struct extcon_dev *edev, u32 state) | ||
| 304 | { | ||
| 305 | return extcon_update_state(edev, 0xffffffff, state); | ||
| 306 | } | ||
| 307 | EXPORT_SYMBOL_GPL(extcon_set_state); | ||
| 308 | |||
| 309 | /** | ||
| 310 | * extcon_find_cable_index() - Get the cable index based on the cable name. | ||
| 311 | * @edev: the extcon device that has the cable. | ||
| 312 | * @cable_name: cable name to be searched. | ||
| 313 | * | ||
| 314 | * Note that accessing a cable state based on cable_index is faster than | ||
| 315 | * cable_name because using cable_name induces a loop with strncmp(). | ||
| 316 | * Thus, when get/set_cable_state is repeatedly used, using cable_index | ||
| 317 | * is recommended. | ||
| 318 | */ | ||
| 319 | int extcon_find_cable_index(struct extcon_dev *edev, const char *cable_name) | ||
| 320 | { | ||
| 321 | int i; | ||
| 322 | |||
| 323 | if (edev->supported_cable) { | ||
| 324 | for (i = 0; edev->supported_cable[i]; i++) { | ||
| 325 | if (!strncmp(edev->supported_cable[i], | ||
| 326 | cable_name, CABLE_NAME_MAX)) | ||
| 327 | return i; | ||
| 328 | } | ||
| 329 | } | ||
| 330 | |||
| 331 | return -EINVAL; | ||
| 332 | } | ||
| 333 | EXPORT_SYMBOL_GPL(extcon_find_cable_index); | ||
| 334 | |||
| 335 | /** | ||
| 336 | * extcon_get_cable_state_() - Get the status of a specific cable. | ||
| 337 | * @edev: the extcon device that has the cable. | ||
| 338 | * @index: cable index that can be retrieved by extcon_find_cable_index(). | ||
| 339 | */ | ||
| 340 | int extcon_get_cable_state_(struct extcon_dev *edev, int index) | ||
| 341 | { | ||
| 342 | if (index < 0 || (edev->max_supported && edev->max_supported <= index)) | ||
| 343 | return -EINVAL; | ||
| 344 | |||
| 345 | return !!(edev->state & (1 << index)); | ||
| 346 | } | ||
| 347 | EXPORT_SYMBOL_GPL(extcon_get_cable_state_); | ||
| 348 | |||
| 349 | /** | ||
| 350 | * extcon_get_cable_state() - Get the status of a specific cable. | ||
| 351 | * @edev: the extcon device that has the cable. | ||
| 352 | * @cable_name: cable name. | ||
| 353 | * | ||
| 354 | * Note that this is slower than extcon_get_cable_state_. | ||
| 355 | */ | ||
| 356 | int extcon_get_cable_state(struct extcon_dev *edev, const char *cable_name) | ||
| 357 | { | ||
| 358 | return extcon_get_cable_state_(edev, extcon_find_cable_index | ||
| 359 | (edev, cable_name)); | ||
| 360 | } | ||
| 361 | EXPORT_SYMBOL_GPL(extcon_get_cable_state); | ||
| 362 | |||
| 363 | /** | ||
| 364 | * extcon_get_cable_state_() - Set the status of a specific cable. | ||
| 365 | * @edev: the extcon device that has the cable. | ||
| 366 | * @index: cable index that can be retrieved by extcon_find_cable_index(). | ||
| 367 | * @cable_state: the new cable status. The default semantics is | ||
| 368 | * true: attached / false: detached. | ||
| 369 | */ | ||
| 370 | int extcon_set_cable_state_(struct extcon_dev *edev, | ||
| 371 | int index, bool cable_state) | ||
| 372 | { | ||
| 373 | u32 state; | ||
| 374 | |||
| 375 | if (index < 0 || (edev->max_supported && edev->max_supported <= index)) | ||
| 376 | return -EINVAL; | ||
| 377 | |||
| 378 | state = cable_state ? (1 << index) : 0; | ||
| 379 | return extcon_update_state(edev, 1 << index, state); | ||
| 380 | } | ||
| 381 | EXPORT_SYMBOL_GPL(extcon_set_cable_state_); | ||
| 382 | |||
| 383 | /** | ||
| 384 | * extcon_get_cable_state() - Set the status of a specific cable. | ||
| 385 | * @edev: the extcon device that has the cable. | ||
| 386 | * @cable_name: cable name. | ||
| 387 | * @cable_state: the new cable status. The default semantics is | ||
| 388 | * true: attached / false: detached. | ||
| 389 | * | ||
| 390 | * Note that this is slower than extcon_set_cable_state_. | ||
| 391 | */ | ||
| 392 | int extcon_set_cable_state(struct extcon_dev *edev, | ||
| 393 | const char *cable_name, bool cable_state) | ||
| 394 | { | ||
| 395 | return extcon_set_cable_state_(edev, extcon_find_cable_index | ||
| 396 | (edev, cable_name), cable_state); | ||
| 397 | } | ||
| 398 | EXPORT_SYMBOL_GPL(extcon_set_cable_state); | ||
| 399 | |||
| 400 | /** | ||
| 401 | * extcon_get_extcon_dev() - Get the extcon device instance from the name | ||
| 402 | * @extcon_name: The extcon name provided with extcon_dev_register() | ||
| 403 | */ | ||
| 404 | struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name) | ||
| 405 | { | ||
| 406 | struct extcon_dev *sd; | ||
| 407 | |||
| 408 | mutex_lock(&extcon_dev_list_lock); | ||
| 409 | list_for_each_entry(sd, &extcon_dev_list, entry) { | ||
| 410 | if (!strcmp(sd->name, extcon_name)) | ||
| 411 | goto out; | ||
| 412 | } | ||
| 413 | sd = NULL; | ||
| 414 | out: | ||
| 415 | mutex_unlock(&extcon_dev_list_lock); | ||
| 416 | return sd; | ||
| 417 | } | ||
| 418 | EXPORT_SYMBOL_GPL(extcon_get_extcon_dev); | ||
| 419 | |||
| 420 | static int _call_per_cable(struct notifier_block *nb, unsigned long val, | ||
| 421 | void *ptr) | ||
| 422 | { | ||
| 423 | struct extcon_specific_cable_nb *obj = container_of(nb, | ||
| 424 | struct extcon_specific_cable_nb, internal_nb); | ||
| 425 | struct extcon_dev *edev = ptr; | ||
| 426 | |||
| 427 | if ((val & (1 << obj->cable_index)) != | ||
| 428 | (edev->state & (1 << obj->cable_index))) { | ||
| 429 | bool cable_state = true; | ||
| 430 | |||
| 431 | obj->previous_value = val; | ||
| 432 | |||
| 433 | if (val & (1 << obj->cable_index)) | ||
| 434 | cable_state = false; | ||
| 435 | |||
| 436 | return obj->user_nb->notifier_call(obj->user_nb, | ||
| 437 | cable_state, ptr); | ||
| 438 | } | ||
| 439 | |||
| 440 | return NOTIFY_OK; | ||
| 441 | } | ||
| 442 | |||
| 443 | /** | ||
| 444 | * extcon_register_interest() - Register a notifier for a state change of a | ||
| 445 | * specific cable, not a entier set of cables of a | ||
| 446 | * extcon device. | ||
| 447 | * @obj: an empty extcon_specific_cable_nb object to be returned. | ||
| 448 | * @extcon_name: the name of extcon device. | ||
| 449 | * @cable_name: the target cable name. | ||
| 450 | * @nb: the notifier block to get notified. | ||
| 451 | * | ||
| 452 | * Provide an empty extcon_specific_cable_nb. extcon_register_interest() sets | ||
| 453 | * the struct for you. | ||
| 454 | * | ||
| 455 | * extcon_register_interest is a helper function for those who want to get | ||
| 456 | * notification for a single specific cable's status change. If a user wants | ||
| 457 | * to get notification for any changes of all cables of a extcon device, | ||
| 458 | * he/she should use the general extcon_register_notifier(). | ||
| 459 | * | ||
| 460 | * Note that the second parameter given to the callback of nb (val) is | ||
| 461 | * "old_state", not the current state. The current state can be retrieved | ||
| 462 | * by looking at the third pameter (edev pointer)'s state value. | ||
| 463 | */ | ||
| 464 | int extcon_register_interest(struct extcon_specific_cable_nb *obj, | ||
| 465 | const char *extcon_name, const char *cable_name, | ||
| 466 | struct notifier_block *nb) | ||
| 467 | { | ||
| 468 | if (!obj || !extcon_name || !cable_name || !nb) | ||
| 469 | return -EINVAL; | ||
| 470 | |||
| 471 | obj->edev = extcon_get_extcon_dev(extcon_name); | ||
| 472 | if (!obj->edev) | ||
| 473 | return -ENODEV; | ||
| 474 | |||
| 475 | obj->cable_index = extcon_find_cable_index(obj->edev, cable_name); | ||
| 476 | if (obj->cable_index < 0) | ||
| 477 | return -ENODEV; | ||
| 478 | |||
| 479 | obj->user_nb = nb; | ||
| 480 | |||
| 481 | obj->internal_nb.notifier_call = _call_per_cable; | ||
| 482 | |||
| 483 | return raw_notifier_chain_register(&obj->edev->nh, &obj->internal_nb); | ||
| 484 | } | ||
| 485 | |||
| 486 | /** | ||
| 487 | * extcon_unregister_interest() - Unregister the notifier registered by | ||
| 488 | * extcon_register_interest(). | ||
| 489 | * @obj: the extcon_specific_cable_nb object returned by | ||
| 490 | * extcon_register_interest(). | ||
| 491 | */ | ||
| 492 | int extcon_unregister_interest(struct extcon_specific_cable_nb *obj) | ||
| 493 | { | ||
| 494 | if (!obj) | ||
| 495 | return -EINVAL; | ||
| 496 | |||
| 497 | return raw_notifier_chain_unregister(&obj->edev->nh, &obj->internal_nb); | ||
| 498 | } | ||
| 499 | |||
| 500 | /** | ||
| 501 | * extcon_register_notifier() - Register a notifee to get notified by | ||
| 502 | * any attach status changes from the extcon. | ||
| 503 | * @edev: the extcon device. | ||
| 504 | * @nb: a notifier block to be registered. | ||
| 505 | * | ||
| 506 | * Note that the second parameter given to the callback of nb (val) is | ||
| 507 | * "old_state", not the current state. The current state can be retrieved | ||
| 508 | * by looking at the third pameter (edev pointer)'s state value. | ||
| 509 | */ | ||
| 510 | int extcon_register_notifier(struct extcon_dev *edev, | ||
| 511 | struct notifier_block *nb) | ||
| 512 | { | ||
| 513 | return raw_notifier_chain_register(&edev->nh, nb); | ||
| 514 | } | ||
| 515 | EXPORT_SYMBOL_GPL(extcon_register_notifier); | ||
| 516 | |||
| 517 | /** | ||
| 518 | * extcon_unregister_notifier() - Unregister a notifee from the extcon device. | ||
| 519 | * @edev: the extcon device. | ||
| 520 | * @nb: a registered notifier block to be unregistered. | ||
| 521 | */ | ||
| 522 | int extcon_unregister_notifier(struct extcon_dev *edev, | ||
| 523 | struct notifier_block *nb) | ||
| 524 | { | ||
| 525 | return raw_notifier_chain_unregister(&edev->nh, nb); | ||
| 526 | } | ||
| 527 | EXPORT_SYMBOL_GPL(extcon_unregister_notifier); | ||
| 528 | |||
| 529 | static struct device_attribute extcon_attrs[] = { | ||
| 530 | __ATTR(state, S_IRUGO | S_IWUSR, state_show, state_store), | ||
| 531 | __ATTR_RO(name), | ||
| 532 | __ATTR_NULL, | ||
| 533 | }; | ||
| 534 | |||
| 535 | static int create_extcon_class(void) | ||
| 536 | { | ||
| 537 | if (!extcon_class) { | ||
| 538 | extcon_class = class_create(THIS_MODULE, "extcon"); | ||
| 539 | if (IS_ERR(extcon_class)) | ||
| 540 | return PTR_ERR(extcon_class); | ||
| 541 | extcon_class->dev_attrs = extcon_attrs; | ||
| 542 | |||
| 543 | #if defined(CONFIG_ANDROID) | ||
| 544 | switch_class = class_compat_register("switch"); | ||
| 545 | if (WARN(!switch_class, "cannot allocate")) | ||
| 546 | return -ENOMEM; | ||
| 547 | #endif /* CONFIG_ANDROID */ | ||
| 548 | } | ||
| 549 | |||
| 550 | return 0; | ||
| 551 | } | ||
| 552 | |||
| 553 | static void extcon_cleanup(struct extcon_dev *edev, bool skip) | ||
| 554 | { | ||
| 555 | mutex_lock(&extcon_dev_list_lock); | ||
| 556 | list_del(&edev->entry); | ||
| 557 | mutex_unlock(&extcon_dev_list_lock); | ||
| 558 | |||
| 559 | if (!skip && get_device(edev->dev)) { | ||
| 560 | int index; | ||
| 561 | |||
| 562 | if (edev->mutually_exclusive && edev->max_supported) { | ||
| 563 | for (index = 0; edev->mutually_exclusive[index]; | ||
| 564 | index++) | ||
| 565 | kfree(edev->d_attrs_muex[index].attr.name); | ||
| 566 | kfree(edev->d_attrs_muex); | ||
| 567 | kfree(edev->attrs_muex); | ||
| 568 | } | ||
| 569 | |||
| 570 | for (index = 0; index < edev->max_supported; index++) | ||
| 571 | kfree(edev->cables[index].attr_g.name); | ||
| 572 | |||
| 573 | if (edev->max_supported) { | ||
| 574 | kfree(edev->extcon_dev_type.groups); | ||
| 575 | kfree(edev->cables); | ||
| 576 | } | ||
| 577 | |||
| 578 | device_unregister(edev->dev); | ||
| 579 | put_device(edev->dev); | ||
| 580 | } | ||
| 581 | |||
| 582 | kfree(edev->dev); | ||
| 583 | } | ||
| 584 | |||
| 585 | static void extcon_dev_release(struct device *dev) | ||
| 586 | { | ||
| 587 | struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev); | ||
| 588 | |||
| 589 | extcon_cleanup(edev, true); | ||
| 590 | } | ||
| 591 | |||
| 592 | static const char *muex_name = "mutually_exclusive"; | ||
| 593 | static void dummy_sysfs_dev_release(struct device *dev) | ||
| 594 | { | ||
| 595 | } | ||
| 596 | |||
| 597 | /** | ||
| 598 | * extcon_dev_register() - Register a new extcon device | ||
| 599 | * @edev : the new extcon device (should be allocated before calling) | ||
| 600 | * @dev : the parent device for this extcon device. | ||
| 601 | * | ||
| 602 | * Among the members of edev struct, please set the "user initializing data" | ||
| 603 | * in any case and set the "optional callbacks" if required. However, please | ||
| 604 | * do not set the values of "internal data", which are initialized by | ||
| 605 | * this function. | ||
| 606 | */ | ||
| 607 | int extcon_dev_register(struct extcon_dev *edev, struct device *dev) | ||
| 608 | { | ||
| 609 | int ret, index = 0; | ||
| 610 | |||
| 611 | if (!extcon_class) { | ||
| 612 | ret = create_extcon_class(); | ||
| 613 | if (ret < 0) | ||
| 614 | return ret; | ||
| 615 | } | ||
| 616 | |||
| 617 | if (edev->supported_cable) { | ||
| 618 | /* Get size of array */ | ||
| 619 | for (index = 0; edev->supported_cable[index]; index++) | ||
| 620 | ; | ||
| 621 | edev->max_supported = index; | ||
| 622 | } else { | ||
| 623 | edev->max_supported = 0; | ||
| 624 | } | ||
| 625 | |||
| 626 | if (index > SUPPORTED_CABLE_MAX) { | ||
| 627 | dev_err(edev->dev, "extcon: maximum number of supported cables exceeded.\n"); | ||
| 628 | return -EINVAL; | ||
| 629 | } | ||
| 630 | |||
| 631 | edev->dev = kzalloc(sizeof(struct device), GFP_KERNEL); | ||
| 632 | if (!edev->dev) | ||
| 633 | return -ENOMEM; | ||
| 634 | edev->dev->parent = dev; | ||
| 635 | edev->dev->class = extcon_class; | ||
| 636 | edev->dev->release = extcon_dev_release; | ||
| 637 | |||
| 638 | dev_set_name(edev->dev, edev->name ? edev->name : dev_name(dev)); | ||
| 639 | |||
| 640 | if (edev->max_supported) { | ||
| 641 | char buf[10]; | ||
| 642 | char *str; | ||
| 643 | struct extcon_cable *cable; | ||
| 644 | |||
| 645 | edev->cables = kzalloc(sizeof(struct extcon_cable) * | ||
| 646 | edev->max_supported, GFP_KERNEL); | ||
| 647 | if (!edev->cables) { | ||
| 648 | ret = -ENOMEM; | ||
| 649 | goto err_sysfs_alloc; | ||
| 650 | } | ||
| 651 | for (index = 0; index < edev->max_supported; index++) { | ||
| 652 | cable = &edev->cables[index]; | ||
| 653 | |||
| 654 | snprintf(buf, 10, "cable.%d", index); | ||
| 655 | str = kzalloc(sizeof(char) * (strlen(buf) + 1), | ||
| 656 | GFP_KERNEL); | ||
| 657 | if (!str) { | ||
| 658 | for (index--; index >= 0; index--) { | ||
| 659 | cable = &edev->cables[index]; | ||
| 660 | kfree(cable->attr_g.name); | ||
| 661 | } | ||
| 662 | ret = -ENOMEM; | ||
| 663 | |||
| 664 | goto err_alloc_cables; | ||
| 665 | } | ||
| 666 | strcpy(str, buf); | ||
| 667 | |||
| 668 | cable->edev = edev; | ||
| 669 | cable->cable_index = index; | ||
| 670 | cable->attrs[0] = &cable->attr_name.attr; | ||
| 671 | cable->attrs[1] = &cable->attr_state.attr; | ||
| 672 | cable->attrs[2] = NULL; | ||
| 673 | cable->attr_g.name = str; | ||
| 674 | cable->attr_g.attrs = cable->attrs; | ||
| 675 | |||
| 676 | cable->attr_name.attr.name = "name"; | ||
| 677 | cable->attr_name.attr.mode = 0444; | ||
| 678 | cable->attr_name.show = cable_name_show; | ||
| 679 | |||
| 680 | cable->attr_state.attr.name = "state"; | ||
| 681 | cable->attr_state.attr.mode = 0644; | ||
| 682 | cable->attr_state.show = cable_state_show; | ||
| 683 | cable->attr_state.store = cable_state_store; | ||
| 684 | } | ||
| 685 | } | ||
| 686 | |||
| 687 | if (edev->max_supported && edev->mutually_exclusive) { | ||
| 688 | char buf[80]; | ||
| 689 | char *name; | ||
| 690 | |||
| 691 | /* Count the size of mutually_exclusive array */ | ||
| 692 | for (index = 0; edev->mutually_exclusive[index]; index++) | ||
| 693 | ; | ||
| 694 | |||
| 695 | edev->attrs_muex = kzalloc(sizeof(struct attribute *) * | ||
| 696 | (index + 1), GFP_KERNEL); | ||
| 697 | if (!edev->attrs_muex) { | ||
| 698 | ret = -ENOMEM; | ||
| 699 | goto err_muex; | ||
| 700 | } | ||
| 701 | |||
| 702 | edev->d_attrs_muex = kzalloc(sizeof(struct device_attribute) * | ||
| 703 | index, GFP_KERNEL); | ||
| 704 | if (!edev->d_attrs_muex) { | ||
| 705 | ret = -ENOMEM; | ||
| 706 | kfree(edev->attrs_muex); | ||
| 707 | goto err_muex; | ||
| 708 | } | ||
| 709 | |||
| 710 | for (index = 0; edev->mutually_exclusive[index]; index++) { | ||
| 711 | sprintf(buf, "0x%x", edev->mutually_exclusive[index]); | ||
| 712 | name = kzalloc(sizeof(char) * (strlen(buf) + 1), | ||
| 713 | GFP_KERNEL); | ||
| 714 | if (!name) { | ||
| 715 | for (index--; index >= 0; index--) { | ||
| 716 | kfree(edev->d_attrs_muex[index].attr. | ||
| 717 | name); | ||
| 718 | } | ||
| 719 | kfree(edev->d_attrs_muex); | ||
| 720 | kfree(edev->attrs_muex); | ||
| 721 | ret = -ENOMEM; | ||
| 722 | goto err_muex; | ||
| 723 | } | ||
| 724 | strcpy(name, buf); | ||
| 725 | edev->d_attrs_muex[index].attr.name = name; | ||
| 726 | edev->d_attrs_muex[index].attr.mode = 0000; | ||
| 727 | edev->attrs_muex[index] = &edev->d_attrs_muex[index] | ||
| 728 | .attr; | ||
| 729 | } | ||
| 730 | edev->attr_g_muex.name = muex_name; | ||
| 731 | edev->attr_g_muex.attrs = edev->attrs_muex; | ||
| 732 | |||
| 733 | } | ||
| 734 | |||
| 735 | if (edev->max_supported) { | ||
| 736 | edev->extcon_dev_type.groups = | ||
| 737 | kzalloc(sizeof(struct attribute_group *) * | ||
| 738 | (edev->max_supported + 2), GFP_KERNEL); | ||
| 739 | if (!edev->extcon_dev_type.groups) { | ||
| 740 | ret = -ENOMEM; | ||
| 741 | goto err_alloc_groups; | ||
| 742 | } | ||
| 743 | |||
| 744 | edev->extcon_dev_type.name = dev_name(edev->dev); | ||
| 745 | edev->extcon_dev_type.release = dummy_sysfs_dev_release; | ||
| 746 | |||
| 747 | for (index = 0; index < edev->max_supported; index++) | ||
| 748 | edev->extcon_dev_type.groups[index] = | ||
| 749 | &edev->cables[index].attr_g; | ||
| 750 | if (edev->mutually_exclusive) | ||
| 751 | edev->extcon_dev_type.groups[index] = | ||
| 752 | &edev->attr_g_muex; | ||
| 753 | |||
| 754 | edev->dev->type = &edev->extcon_dev_type; | ||
| 755 | } | ||
| 756 | |||
| 757 | ret = device_register(edev->dev); | ||
| 758 | if (ret) { | ||
| 759 | put_device(edev->dev); | ||
| 760 | goto err_dev; | ||
| 761 | } | ||
| 762 | #if defined(CONFIG_ANDROID) | ||
| 763 | if (switch_class) | ||
| 764 | ret = class_compat_create_link(switch_class, edev->dev, | ||
| 765 | dev); | ||
| 766 | #endif /* CONFIG_ANDROID */ | ||
| 767 | |||
| 768 | spin_lock_init(&edev->lock); | ||
| 769 | |||
| 770 | RAW_INIT_NOTIFIER_HEAD(&edev->nh); | ||
| 771 | |||
| 772 | dev_set_drvdata(edev->dev, edev); | ||
| 773 | edev->state = 0; | ||
| 774 | |||
| 775 | mutex_lock(&extcon_dev_list_lock); | ||
| 776 | list_add(&edev->entry, &extcon_dev_list); | ||
| 777 | mutex_unlock(&extcon_dev_list_lock); | ||
| 778 | |||
| 779 | return 0; | ||
| 780 | |||
| 781 | err_dev: | ||
| 782 | if (edev->max_supported) | ||
| 783 | kfree(edev->extcon_dev_type.groups); | ||
| 784 | err_alloc_groups: | ||
| 785 | if (edev->max_supported && edev->mutually_exclusive) { | ||
| 786 | for (index = 0; edev->mutually_exclusive[index]; index++) | ||
| 787 | kfree(edev->d_attrs_muex[index].attr.name); | ||
| 788 | kfree(edev->d_attrs_muex); | ||
| 789 | kfree(edev->attrs_muex); | ||
| 790 | } | ||
| 791 | err_muex: | ||
| 792 | for (index = 0; index < edev->max_supported; index++) | ||
| 793 | kfree(edev->cables[index].attr_g.name); | ||
| 794 | err_alloc_cables: | ||
| 795 | if (edev->max_supported) | ||
| 796 | kfree(edev->cables); | ||
| 797 | err_sysfs_alloc: | ||
| 798 | kfree(edev->dev); | ||
| 799 | return ret; | ||
| 800 | } | ||
| 801 | EXPORT_SYMBOL_GPL(extcon_dev_register); | ||
| 802 | |||
| 803 | /** | ||
| 804 | * extcon_dev_unregister() - Unregister the extcon device. | ||
| 805 | * @edev: the extcon device instance to be unregitered. | ||
| 806 | * | ||
| 807 | * Note that this does not call kfree(edev) because edev was not allocated | ||
| 808 | * by this class. | ||
| 809 | */ | ||
| 810 | void extcon_dev_unregister(struct extcon_dev *edev) | ||
| 811 | { | ||
| 812 | extcon_cleanup(edev, false); | ||
| 813 | } | ||
| 814 | EXPORT_SYMBOL_GPL(extcon_dev_unregister); | ||
| 815 | |||
| 816 | static int __init extcon_class_init(void) | ||
| 817 | { | ||
| 818 | return create_extcon_class(); | ||
| 819 | } | ||
| 820 | module_init(extcon_class_init); | ||
| 821 | |||
| 822 | static void __exit extcon_class_exit(void) | ||
| 823 | { | ||
| 824 | class_destroy(extcon_class); | ||
| 825 | } | ||
| 826 | module_exit(extcon_class_exit); | ||
| 827 | |||
| 828 | MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>"); | ||
| 829 | MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>"); | ||
| 830 | MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); | ||
| 831 | MODULE_DESCRIPTION("External connector (extcon) class driver"); | ||
| 832 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/extcon/extcon_gpio.c b/drivers/extcon/extcon_gpio.c new file mode 100644 index 000000000000..fe7a07b47336 --- /dev/null +++ b/drivers/extcon/extcon_gpio.c | |||
| @@ -0,0 +1,169 @@ | |||
| 1 | /* | ||
| 2 | * drivers/extcon/extcon_gpio.c | ||
| 3 | * | ||
| 4 | * Single-state GPIO extcon driver based on extcon class | ||
| 5 | * | ||
| 6 | * Copyright (C) 2008 Google, Inc. | ||
| 7 | * Author: Mike Lockwood <lockwood@android.com> | ||
| 8 | * | ||
| 9 | * Modified by MyungJoo Ham <myungjoo.ham@samsung.com> to support extcon | ||
| 10 | * (originally switch class is supported) | ||
| 11 | * | ||
| 12 | * This software is licensed under the terms of the GNU General Public | ||
| 13 | * License version 2, as published by the Free Software Foundation, and | ||
| 14 | * may be copied, distributed, and modified under those terms. | ||
| 15 | * | ||
| 16 | * This program is distributed in the hope that it will be useful, | ||
| 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 19 | * GNU General Public License for more details. | ||
| 20 | * | ||
| 21 | */ | ||
| 22 | |||
| 23 | #include <linux/module.h> | ||
| 24 | #include <linux/kernel.h> | ||
| 25 | #include <linux/init.h> | ||
| 26 | #include <linux/interrupt.h> | ||
| 27 | #include <linux/platform_device.h> | ||
| 28 | #include <linux/slab.h> | ||
| 29 | #include <linux/extcon.h> | ||
| 30 | #include <linux/workqueue.h> | ||
| 31 | #include <linux/gpio.h> | ||
| 32 | #include <linux/extcon.h> | ||
| 33 | #include <linux/extcon/extcon_gpio.h> | ||
| 34 | |||
| 35 | struct gpio_extcon_data { | ||
| 36 | struct extcon_dev edev; | ||
| 37 | unsigned gpio; | ||
| 38 | const char *state_on; | ||
| 39 | const char *state_off; | ||
| 40 | int irq; | ||
| 41 | struct delayed_work work; | ||
| 42 | unsigned long debounce_jiffies; | ||
| 43 | }; | ||
| 44 | |||
| 45 | static void gpio_extcon_work(struct work_struct *work) | ||
| 46 | { | ||
| 47 | int state; | ||
| 48 | struct gpio_extcon_data *data = | ||
| 49 | container_of(to_delayed_work(work), struct gpio_extcon_data, | ||
| 50 | work); | ||
| 51 | |||
| 52 | state = gpio_get_value(data->gpio); | ||
| 53 | extcon_set_state(&data->edev, state); | ||
| 54 | } | ||
| 55 | |||
| 56 | static irqreturn_t gpio_irq_handler(int irq, void *dev_id) | ||
| 57 | { | ||
| 58 | struct gpio_extcon_data *extcon_data = dev_id; | ||
| 59 | |||
| 60 | schedule_delayed_work(&extcon_data->work, | ||
| 61 | extcon_data->debounce_jiffies); | ||
| 62 | return IRQ_HANDLED; | ||
| 63 | } | ||
| 64 | |||
| 65 | static ssize_t extcon_gpio_print_state(struct extcon_dev *edev, char *buf) | ||
| 66 | { | ||
| 67 | struct gpio_extcon_data *extcon_data = | ||
| 68 | container_of(edev, struct gpio_extcon_data, edev); | ||
| 69 | const char *state; | ||
| 70 | if (extcon_get_state(edev)) | ||
| 71 | state = extcon_data->state_on; | ||
| 72 | else | ||
| 73 | state = extcon_data->state_off; | ||
| 74 | |||
| 75 | if (state) | ||
| 76 | return sprintf(buf, "%s\n", state); | ||
| 77 | return -EINVAL; | ||
| 78 | } | ||
| 79 | |||
| 80 | static int __devinit gpio_extcon_probe(struct platform_device *pdev) | ||
| 81 | { | ||
| 82 | struct gpio_extcon_platform_data *pdata = pdev->dev.platform_data; | ||
| 83 | struct gpio_extcon_data *extcon_data; | ||
| 84 | int ret = 0; | ||
| 85 | |||
| 86 | if (!pdata) | ||
| 87 | return -EBUSY; | ||
| 88 | if (!pdata->irq_flags) { | ||
| 89 | dev_err(&pdev->dev, "IRQ flag is not specified.\n"); | ||
| 90 | return -EINVAL; | ||
| 91 | } | ||
| 92 | |||
| 93 | extcon_data = devm_kzalloc(&pdev->dev, sizeof(struct gpio_extcon_data), | ||
| 94 | GFP_KERNEL); | ||
| 95 | if (!extcon_data) | ||
| 96 | return -ENOMEM; | ||
| 97 | |||
| 98 | extcon_data->edev.name = pdata->name; | ||
| 99 | extcon_data->gpio = pdata->gpio; | ||
| 100 | extcon_data->state_on = pdata->state_on; | ||
| 101 | extcon_data->state_off = pdata->state_off; | ||
| 102 | if (pdata->state_on && pdata->state_off) | ||
| 103 | extcon_data->edev.print_state = extcon_gpio_print_state; | ||
| 104 | extcon_data->debounce_jiffies = msecs_to_jiffies(pdata->debounce); | ||
| 105 | |||
| 106 | ret = extcon_dev_register(&extcon_data->edev, &pdev->dev); | ||
| 107 | if (ret < 0) | ||
| 108 | goto err_extcon_dev_register; | ||
| 109 | |||
| 110 | ret = gpio_request_one(extcon_data->gpio, GPIOF_DIR_IN, pdev->name); | ||
| 111 | if (ret < 0) | ||
| 112 | goto err_request_gpio; | ||
| 113 | |||
| 114 | INIT_DELAYED_WORK(&extcon_data->work, gpio_extcon_work); | ||
| 115 | |||
| 116 | extcon_data->irq = gpio_to_irq(extcon_data->gpio); | ||
| 117 | if (extcon_data->irq < 0) { | ||
| 118 | ret = extcon_data->irq; | ||
| 119 | goto err_detect_irq_num_failed; | ||
| 120 | } | ||
| 121 | |||
| 122 | ret = request_any_context_irq(extcon_data->irq, gpio_irq_handler, | ||
| 123 | pdata->irq_flags, pdev->name, | ||
| 124 | extcon_data); | ||
| 125 | if (ret < 0) | ||
| 126 | goto err_request_irq; | ||
| 127 | |||
| 128 | /* Perform initial detection */ | ||
| 129 | gpio_extcon_work(&extcon_data->work.work); | ||
| 130 | |||
| 131 | return 0; | ||
| 132 | |||
| 133 | err_request_irq: | ||
| 134 | err_detect_irq_num_failed: | ||
| 135 | gpio_free(extcon_data->gpio); | ||
| 136 | err_request_gpio: | ||
| 137 | extcon_dev_unregister(&extcon_data->edev); | ||
| 138 | err_extcon_dev_register: | ||
| 139 | devm_kfree(&pdev->dev, extcon_data); | ||
| 140 | |||
| 141 | return ret; | ||
| 142 | } | ||
| 143 | |||
| 144 | static int __devexit gpio_extcon_remove(struct platform_device *pdev) | ||
| 145 | { | ||
| 146 | struct gpio_extcon_data *extcon_data = platform_get_drvdata(pdev); | ||
| 147 | |||
| 148 | cancel_delayed_work_sync(&extcon_data->work); | ||
| 149 | gpio_free(extcon_data->gpio); | ||
| 150 | extcon_dev_unregister(&extcon_data->edev); | ||
| 151 | devm_kfree(&pdev->dev, extcon_data); | ||
| 152 | |||
| 153 | return 0; | ||
| 154 | } | ||
| 155 | |||
| 156 | static struct platform_driver gpio_extcon_driver = { | ||
| 157 | .probe = gpio_extcon_probe, | ||
| 158 | .remove = __devexit_p(gpio_extcon_remove), | ||
| 159 | .driver = { | ||
| 160 | .name = "extcon-gpio", | ||
| 161 | .owner = THIS_MODULE, | ||
| 162 | }, | ||
| 163 | }; | ||
| 164 | |||
| 165 | module_platform_driver(gpio_extcon_driver); | ||
| 166 | |||
| 167 | MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>"); | ||
| 168 | MODULE_DESCRIPTION("GPIO extcon driver"); | ||
| 169 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/gpio/devres.c b/drivers/gpio/devres.c index 3dd29399cef5..8950f6261bbb 100644 --- a/drivers/gpio/devres.c +++ b/drivers/gpio/devres.c | |||
| @@ -83,8 +83,7 @@ EXPORT_SYMBOL(devm_gpio_request); | |||
| 83 | void devm_gpio_free(struct device *dev, unsigned int gpio) | 83 | void devm_gpio_free(struct device *dev, unsigned int gpio) |
| 84 | { | 84 | { |
| 85 | 85 | ||
| 86 | WARN_ON(devres_destroy(dev, devm_gpio_release, devm_gpio_match, | 86 | WARN_ON(devres_release(dev, devm_gpio_release, devm_gpio_match, |
| 87 | &gpio)); | 87 | &gpio)); |
| 88 | gpio_free(gpio); | ||
| 89 | } | 88 | } |
| 90 | EXPORT_SYMBOL(devm_gpio_free); | 89 | EXPORT_SYMBOL(devm_gpio_free); |
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 9ffbfc575a0c..2b8b8d4558d2 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c | |||
| @@ -46,40 +46,61 @@ struct vmbus_channel_message_table_entry { | |||
| 46 | * | 46 | * |
| 47 | * @icmsghdrp is of type &struct icmsg_hdr. | 47 | * @icmsghdrp is of type &struct icmsg_hdr. |
| 48 | * @negop is of type &struct icmsg_negotiate. | 48 | * @negop is of type &struct icmsg_negotiate. |
| 49 | * Set up and fill in default negotiate response message. This response can | 49 | * Set up and fill in default negotiate response message. |
| 50 | * come from both the vmbus driver and the hv_utils driver. The current api | 50 | * |
| 51 | * will respond properly to both Windows 2008 and Windows 2008-R2 operating | 51 | * The max_fw_version specifies the maximum framework version that |
| 52 | * systems. | 52 | * we can support and max _srv_version specifies the maximum service |
| 53 | * version we can support. A special value MAX_SRV_VER can be | ||
| 54 | * specified to indicate that we can handle the maximum version | ||
| 55 | * exposed by the host. | ||
| 53 | * | 56 | * |
| 54 | * Mainly used by Hyper-V drivers. | 57 | * Mainly used by Hyper-V drivers. |
| 55 | */ | 58 | */ |
| 56 | void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, | 59 | void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, |
| 57 | struct icmsg_negotiate *negop, u8 *buf) | 60 | struct icmsg_negotiate *negop, u8 *buf, |
| 61 | int max_fw_version, int max_srv_version) | ||
| 58 | { | 62 | { |
| 59 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { | 63 | int icframe_vercnt; |
| 60 | icmsghdrp->icmsgsize = 0x10; | 64 | int icmsg_vercnt; |
| 61 | 65 | int i; | |
| 62 | negop = (struct icmsg_negotiate *)&buf[ | 66 | |
| 63 | sizeof(struct vmbuspipe_hdr) + | 67 | icmsghdrp->icmsgsize = 0x10; |
| 64 | sizeof(struct icmsg_hdr)]; | 68 | |
| 65 | 69 | negop = (struct icmsg_negotiate *)&buf[ | |
| 66 | if (negop->icframe_vercnt == 2 && | 70 | sizeof(struct vmbuspipe_hdr) + |
| 67 | negop->icversion_data[1].major == 3) { | 71 | sizeof(struct icmsg_hdr)]; |
| 68 | negop->icversion_data[0].major = 3; | 72 | |
| 69 | negop->icversion_data[0].minor = 0; | 73 | icframe_vercnt = negop->icframe_vercnt; |
| 70 | negop->icversion_data[1].major = 3; | 74 | icmsg_vercnt = negop->icmsg_vercnt; |
| 71 | negop->icversion_data[1].minor = 0; | 75 | |
| 72 | } else { | 76 | /* |
| 73 | negop->icversion_data[0].major = 1; | 77 | * Select the framework version number we will |
| 74 | negop->icversion_data[0].minor = 0; | 78 | * support. |
| 75 | negop->icversion_data[1].major = 1; | 79 | */ |
| 76 | negop->icversion_data[1].minor = 0; | 80 | |
| 77 | } | 81 | for (i = 0; i < negop->icframe_vercnt; i++) { |
| 82 | if (negop->icversion_data[i].major <= max_fw_version) | ||
| 83 | icframe_vercnt = negop->icversion_data[i].major; | ||
| 84 | } | ||
| 78 | 85 | ||
| 79 | negop->icframe_vercnt = 1; | 86 | for (i = negop->icframe_vercnt; |
| 80 | negop->icmsg_vercnt = 1; | 87 | (i < negop->icframe_vercnt + negop->icmsg_vercnt); i++) { |
| 88 | if (negop->icversion_data[i].major <= max_srv_version) | ||
| 89 | icmsg_vercnt = negop->icversion_data[i].major; | ||
| 81 | } | 90 | } |
| 91 | |||
| 92 | /* | ||
| 93 | * Respond with the maximum framework and service | ||
| 94 | * version numbers we can support. | ||
| 95 | */ | ||
| 96 | negop->icframe_vercnt = 1; | ||
| 97 | negop->icmsg_vercnt = 1; | ||
| 98 | negop->icversion_data[0].major = icframe_vercnt; | ||
| 99 | negop->icversion_data[0].minor = 0; | ||
| 100 | negop->icversion_data[1].major = icmsg_vercnt; | ||
| 101 | negop->icversion_data[1].minor = 0; | ||
| 82 | } | 102 | } |
| 103 | |||
| 83 | EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp); | 104 | EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp); |
| 84 | 105 | ||
| 85 | /* | 106 | /* |
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 15956bd48b48..86f8885aeb45 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c | |||
| @@ -252,7 +252,7 @@ void hv_cleanup(void) | |||
| 252 | * | 252 | * |
| 253 | * This involves a hypercall. | 253 | * This involves a hypercall. |
| 254 | */ | 254 | */ |
| 255 | u16 hv_post_message(union hv_connection_id connection_id, | 255 | int hv_post_message(union hv_connection_id connection_id, |
| 256 | enum hv_message_type message_type, | 256 | enum hv_message_type message_type, |
| 257 | void *payload, size_t payload_size) | 257 | void *payload, size_t payload_size) |
| 258 | { | 258 | { |
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c index 6186025209ce..0012eed6d872 100644 --- a/drivers/hv/hv_kvp.c +++ b/drivers/hv/hv_kvp.c | |||
| @@ -394,7 +394,8 @@ void hv_kvp_onchannelcallback(void *context) | |||
| 394 | sizeof(struct vmbuspipe_hdr)]; | 394 | sizeof(struct vmbuspipe_hdr)]; |
| 395 | 395 | ||
| 396 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { | 396 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { |
| 397 | vmbus_prep_negotiate_resp(icmsghdrp, negop, recv_buffer); | 397 | vmbus_prep_negotiate_resp(icmsghdrp, negop, |
| 398 | recv_buffer, MAX_SRV_VER, MAX_SRV_VER); | ||
| 398 | } else { | 399 | } else { |
| 399 | kvp_msg = (struct hv_kvp_msg *)&recv_buffer[ | 400 | kvp_msg = (struct hv_kvp_msg *)&recv_buffer[ |
| 400 | sizeof(struct vmbuspipe_hdr) + | 401 | sizeof(struct vmbuspipe_hdr) + |
diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c index dbb8b8eec210..d3ac6a40118b 100644 --- a/drivers/hv/hv_util.c +++ b/drivers/hv/hv_util.c | |||
| @@ -70,7 +70,8 @@ static void shutdown_onchannelcallback(void *context) | |||
| 70 | sizeof(struct vmbuspipe_hdr)]; | 70 | sizeof(struct vmbuspipe_hdr)]; |
| 71 | 71 | ||
| 72 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { | 72 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { |
| 73 | vmbus_prep_negotiate_resp(icmsghdrp, negop, shut_txf_buf); | 73 | vmbus_prep_negotiate_resp(icmsghdrp, negop, |
| 74 | shut_txf_buf, MAX_SRV_VER, MAX_SRV_VER); | ||
| 74 | } else { | 75 | } else { |
| 75 | shutdown_msg = | 76 | shutdown_msg = |
| 76 | (struct shutdown_msg_data *)&shut_txf_buf[ | 77 | (struct shutdown_msg_data *)&shut_txf_buf[ |
| @@ -195,7 +196,8 @@ static void timesync_onchannelcallback(void *context) | |||
| 195 | sizeof(struct vmbuspipe_hdr)]; | 196 | sizeof(struct vmbuspipe_hdr)]; |
| 196 | 197 | ||
| 197 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { | 198 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { |
| 198 | vmbus_prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf); | 199 | vmbus_prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf, |
| 200 | MAX_SRV_VER, MAX_SRV_VER); | ||
| 199 | } else { | 201 | } else { |
| 200 | timedatap = (struct ictimesync_data *)&time_txf_buf[ | 202 | timedatap = (struct ictimesync_data *)&time_txf_buf[ |
| 201 | sizeof(struct vmbuspipe_hdr) + | 203 | sizeof(struct vmbuspipe_hdr) + |
| @@ -234,7 +236,8 @@ static void heartbeat_onchannelcallback(void *context) | |||
| 234 | sizeof(struct vmbuspipe_hdr)]; | 236 | sizeof(struct vmbuspipe_hdr)]; |
| 235 | 237 | ||
| 236 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { | 238 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { |
| 237 | vmbus_prep_negotiate_resp(icmsghdrp, NULL, hbeat_txf_buf); | 239 | vmbus_prep_negotiate_resp(icmsghdrp, NULL, |
| 240 | hbeat_txf_buf, MAX_SRV_VER, MAX_SRV_VER); | ||
| 238 | } else { | 241 | } else { |
| 239 | heartbeat_msg = | 242 | heartbeat_msg = |
| 240 | (struct heartbeat_msg_data *)&hbeat_txf_buf[ | 243 | (struct heartbeat_msg_data *)&hbeat_txf_buf[ |
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 699f0d8e59ed..b9426a6592ee 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h | |||
| @@ -495,7 +495,7 @@ extern int hv_init(void); | |||
| 495 | 495 | ||
| 496 | extern void hv_cleanup(void); | 496 | extern void hv_cleanup(void); |
| 497 | 497 | ||
| 498 | extern u16 hv_post_message(union hv_connection_id connection_id, | 498 | extern int hv_post_message(union hv_connection_id connection_id, |
| 499 | enum hv_message_type message_type, | 499 | enum hv_message_type message_type, |
| 500 | void *payload, size_t payload_size); | 500 | void *payload, size_t payload_size); |
| 501 | 501 | ||
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig new file mode 100644 index 000000000000..067f31174a0e --- /dev/null +++ b/drivers/memory/Kconfig | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | # | ||
| 2 | # Memory devices | ||
| 3 | # | ||
| 4 | |||
| 5 | menuconfig MEMORY | ||
| 6 | bool "Memory Controller drivers" | ||
| 7 | |||
| 8 | if MEMORY | ||
| 9 | |||
| 10 | config TI_EMIF | ||
| 11 | tristate "Texas Instruments EMIF driver" | ||
| 12 | depends on ARCH_OMAP2PLUS | ||
| 13 | select DDR | ||
| 14 | help | ||
| 15 | This driver is for the EMIF module available in Texas Instruments | ||
| 16 | SoCs. EMIF is an SDRAM controller that, based on its revision, | ||
| 17 | supports one or more of DDR2, DDR3, and LPDDR2 SDRAM protocols. | ||
| 18 | This driver takes care of only LPDDR2 memories presently. The | ||
| 19 | functions of the driver includes re-configuring AC timing | ||
| 20 | parameters and other settings during frequency, voltage and | ||
| 21 | temperature changes | ||
| 22 | |||
| 23 | config TEGRA20_MC | ||
| 24 | bool "Tegra20 Memory Controller(MC) driver" | ||
| 25 | default y | ||
| 26 | depends on ARCH_TEGRA_2x_SOC | ||
| 27 | help | ||
| 28 | This driver is for the Memory Controller(MC) module available | ||
| 29 | in Tegra20 SoCs, mainly for a address translation fault | ||
| 30 | analysis, especially for IOMMU/GART(Graphics Address | ||
| 31 | Relocation Table) module. | ||
| 32 | |||
| 33 | config TEGRA30_MC | ||
| 34 | bool "Tegra30 Memory Controller(MC) driver" | ||
| 35 | default y | ||
| 36 | depends on ARCH_TEGRA_3x_SOC | ||
| 37 | help | ||
| 38 | This driver is for the Memory Controller(MC) module available | ||
| 39 | in Tegra30 SoCs, mainly for a address translation fault | ||
| 40 | analysis, especially for IOMMU/SMMU(System Memory Management | ||
| 41 | Unit) module. | ||
| 42 | |||
| 43 | endif | ||
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile new file mode 100644 index 000000000000..42b3ce9d80fc --- /dev/null +++ b/drivers/memory/Makefile | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | # | ||
| 2 | # Makefile for memory devices | ||
| 3 | # | ||
| 4 | |||
| 5 | obj-$(CONFIG_TI_EMIF) += emif.o | ||
| 6 | obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o | ||
| 7 | obj-$(CONFIG_TEGRA30_MC) += tegra30-mc.o | ||
diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c new file mode 100644 index 000000000000..33a4396b24cb --- /dev/null +++ b/drivers/memory/emif.c | |||
| @@ -0,0 +1,1670 @@ | |||
| 1 | /* | ||
| 2 | * EMIF driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Texas Instruments, Inc. | ||
| 5 | * | ||
| 6 | * Aneesh V <aneesh@ti.com> | ||
| 7 | * Santosh Shilimkar <santosh.shilimkar@ti.com> | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License version 2 as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | */ | ||
| 13 | #include <linux/kernel.h> | ||
| 14 | #include <linux/reboot.h> | ||
| 15 | #include <linux/platform_data/emif_plat.h> | ||
| 16 | #include <linux/io.h> | ||
| 17 | #include <linux/device.h> | ||
| 18 | #include <linux/platform_device.h> | ||
| 19 | #include <linux/interrupt.h> | ||
| 20 | #include <linux/slab.h> | ||
| 21 | #include <linux/debugfs.h> | ||
| 22 | #include <linux/seq_file.h> | ||
| 23 | #include <linux/module.h> | ||
| 24 | #include <linux/list.h> | ||
| 25 | #include <linux/spinlock.h> | ||
| 26 | #include <memory/jedec_ddr.h> | ||
| 27 | #include "emif.h" | ||
| 28 | |||
| 29 | /** | ||
| 30 | * struct emif_data - Per device static data for driver's use | ||
| 31 | * @duplicate: Whether the DDR devices attached to this EMIF | ||
| 32 | * instance are exactly same as that on EMIF1. In | ||
| 33 | * this case we can save some memory and processing | ||
| 34 | * @temperature_level: Maximum temperature of LPDDR2 devices attached | ||
| 35 | * to this EMIF - read from MR4 register. If there | ||
| 36 | * are two devices attached to this EMIF, this | ||
| 37 | * value is the maximum of the two temperature | ||
| 38 | * levels. | ||
| 39 | * @node: node in the device list | ||
| 40 | * @base: base address of memory-mapped IO registers. | ||
| 41 | * @dev: device pointer. | ||
| 42 | * @addressing table with addressing information from the spec | ||
| 43 | * @regs_cache: An array of 'struct emif_regs' that stores | ||
| 44 | * calculated register values for different | ||
| 45 | * frequencies, to avoid re-calculating them on | ||
| 46 | * each DVFS transition. | ||
| 47 | * @curr_regs: The set of register values used in the last | ||
| 48 | * frequency change (i.e. corresponding to the | ||
| 49 | * frequency in effect at the moment) | ||
| 50 | * @plat_data: Pointer to saved platform data. | ||
| 51 | * @debugfs_root: dentry to the root folder for EMIF in debugfs | ||
| 52 | */ | ||
| 53 | struct emif_data { | ||
| 54 | u8 duplicate; | ||
| 55 | u8 temperature_level; | ||
| 56 | u8 lpmode; | ||
| 57 | struct list_head node; | ||
| 58 | unsigned long irq_state; | ||
| 59 | void __iomem *base; | ||
| 60 | struct device *dev; | ||
| 61 | const struct lpddr2_addressing *addressing; | ||
| 62 | struct emif_regs *regs_cache[EMIF_MAX_NUM_FREQUENCIES]; | ||
| 63 | struct emif_regs *curr_regs; | ||
| 64 | struct emif_platform_data *plat_data; | ||
| 65 | struct dentry *debugfs_root; | ||
| 66 | }; | ||
| 67 | |||
| 68 | static struct emif_data *emif1; | ||
| 69 | static spinlock_t emif_lock; | ||
| 70 | static unsigned long irq_state; | ||
| 71 | static u32 t_ck; /* DDR clock period in ps */ | ||
| 72 | static LIST_HEAD(device_list); | ||
| 73 | |||
| 74 | static void do_emif_regdump_show(struct seq_file *s, struct emif_data *emif, | ||
| 75 | struct emif_regs *regs) | ||
| 76 | { | ||
| 77 | u32 type = emif->plat_data->device_info->type; | ||
| 78 | u32 ip_rev = emif->plat_data->ip_rev; | ||
| 79 | |||
| 80 | seq_printf(s, "EMIF register cache dump for %dMHz\n", | ||
| 81 | regs->freq/1000000); | ||
| 82 | |||
| 83 | seq_printf(s, "ref_ctrl_shdw\t: 0x%08x\n", regs->ref_ctrl_shdw); | ||
| 84 | seq_printf(s, "sdram_tim1_shdw\t: 0x%08x\n", regs->sdram_tim1_shdw); | ||
| 85 | seq_printf(s, "sdram_tim2_shdw\t: 0x%08x\n", regs->sdram_tim2_shdw); | ||
| 86 | seq_printf(s, "sdram_tim3_shdw\t: 0x%08x\n", regs->sdram_tim3_shdw); | ||
| 87 | |||
| 88 | if (ip_rev == EMIF_4D) { | ||
| 89 | seq_printf(s, "read_idle_ctrl_shdw_normal\t: 0x%08x\n", | ||
| 90 | regs->read_idle_ctrl_shdw_normal); | ||
| 91 | seq_printf(s, "read_idle_ctrl_shdw_volt_ramp\t: 0x%08x\n", | ||
| 92 | regs->read_idle_ctrl_shdw_volt_ramp); | ||
| 93 | } else if (ip_rev == EMIF_4D5) { | ||
| 94 | seq_printf(s, "dll_calib_ctrl_shdw_normal\t: 0x%08x\n", | ||
| 95 | regs->dll_calib_ctrl_shdw_normal); | ||
| 96 | seq_printf(s, "dll_calib_ctrl_shdw_volt_ramp\t: 0x%08x\n", | ||
| 97 | regs->dll_calib_ctrl_shdw_volt_ramp); | ||
| 98 | } | ||
| 99 | |||
| 100 | if (type == DDR_TYPE_LPDDR2_S2 || type == DDR_TYPE_LPDDR2_S4) { | ||
| 101 | seq_printf(s, "ref_ctrl_shdw_derated\t: 0x%08x\n", | ||
| 102 | regs->ref_ctrl_shdw_derated); | ||
| 103 | seq_printf(s, "sdram_tim1_shdw_derated\t: 0x%08x\n", | ||
| 104 | regs->sdram_tim1_shdw_derated); | ||
| 105 | seq_printf(s, "sdram_tim3_shdw_derated\t: 0x%08x\n", | ||
| 106 | regs->sdram_tim3_shdw_derated); | ||
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 110 | static int emif_regdump_show(struct seq_file *s, void *unused) | ||
| 111 | { | ||
| 112 | struct emif_data *emif = s->private; | ||
| 113 | struct emif_regs **regs_cache; | ||
| 114 | int i; | ||
| 115 | |||
| 116 | if (emif->duplicate) | ||
| 117 | regs_cache = emif1->regs_cache; | ||
| 118 | else | ||
| 119 | regs_cache = emif->regs_cache; | ||
| 120 | |||
| 121 | for (i = 0; i < EMIF_MAX_NUM_FREQUENCIES && regs_cache[i]; i++) { | ||
| 122 | do_emif_regdump_show(s, emif, regs_cache[i]); | ||
| 123 | seq_printf(s, "\n"); | ||
| 124 | } | ||
| 125 | |||
| 126 | return 0; | ||
| 127 | } | ||
| 128 | |||
| 129 | static int emif_regdump_open(struct inode *inode, struct file *file) | ||
| 130 | { | ||
| 131 | return single_open(file, emif_regdump_show, inode->i_private); | ||
| 132 | } | ||
| 133 | |||
| 134 | static const struct file_operations emif_regdump_fops = { | ||
| 135 | .open = emif_regdump_open, | ||
| 136 | .read = seq_read, | ||
| 137 | .release = single_release, | ||
| 138 | }; | ||
| 139 | |||
| 140 | static int emif_mr4_show(struct seq_file *s, void *unused) | ||
| 141 | { | ||
| 142 | struct emif_data *emif = s->private; | ||
| 143 | |||
| 144 | seq_printf(s, "MR4=%d\n", emif->temperature_level); | ||
| 145 | return 0; | ||
| 146 | } | ||
| 147 | |||
| 148 | static int emif_mr4_open(struct inode *inode, struct file *file) | ||
| 149 | { | ||
| 150 | return single_open(file, emif_mr4_show, inode->i_private); | ||
| 151 | } | ||
| 152 | |||
| 153 | static const struct file_operations emif_mr4_fops = { | ||
| 154 | .open = emif_mr4_open, | ||
| 155 | .read = seq_read, | ||
| 156 | .release = single_release, | ||
| 157 | }; | ||
| 158 | |||
| 159 | static int __init_or_module emif_debugfs_init(struct emif_data *emif) | ||
| 160 | { | ||
| 161 | struct dentry *dentry; | ||
| 162 | int ret; | ||
| 163 | |||
| 164 | dentry = debugfs_create_dir(dev_name(emif->dev), NULL); | ||
| 165 | if (IS_ERR(dentry)) { | ||
| 166 | ret = PTR_ERR(dentry); | ||
| 167 | goto err0; | ||
| 168 | } | ||
| 169 | emif->debugfs_root = dentry; | ||
| 170 | |||
| 171 | dentry = debugfs_create_file("regcache_dump", S_IRUGO, | ||
| 172 | emif->debugfs_root, emif, &emif_regdump_fops); | ||
| 173 | if (IS_ERR(dentry)) { | ||
| 174 | ret = PTR_ERR(dentry); | ||
| 175 | goto err1; | ||
| 176 | } | ||
| 177 | |||
| 178 | dentry = debugfs_create_file("mr4", S_IRUGO, | ||
| 179 | emif->debugfs_root, emif, &emif_mr4_fops); | ||
| 180 | if (IS_ERR(dentry)) { | ||
| 181 | ret = PTR_ERR(dentry); | ||
| 182 | goto err1; | ||
| 183 | } | ||
| 184 | |||
| 185 | return 0; | ||
| 186 | err1: | ||
| 187 | debugfs_remove_recursive(emif->debugfs_root); | ||
| 188 | err0: | ||
| 189 | return ret; | ||
| 190 | } | ||
| 191 | |||
| 192 | static void __exit emif_debugfs_exit(struct emif_data *emif) | ||
| 193 | { | ||
| 194 | debugfs_remove_recursive(emif->debugfs_root); | ||
| 195 | emif->debugfs_root = NULL; | ||
| 196 | } | ||
| 197 | |||
| 198 | /* | ||
| 199 | * Calculate the period of DDR clock from frequency value | ||
| 200 | */ | ||
| 201 | static void set_ddr_clk_period(u32 freq) | ||
| 202 | { | ||
| 203 | /* Divide 10^12 by frequency to get period in ps */ | ||
| 204 | t_ck = (u32)DIV_ROUND_UP_ULL(1000000000000ull, freq); | ||
| 205 | } | ||
| 206 | |||
| 207 | /* | ||
| 208 | * Get bus width used by EMIF. Note that this may be different from the | ||
| 209 | * bus width of the DDR devices used. For instance two 16-bit DDR devices | ||
| 210 | * may be connected to a given CS of EMIF. In this case bus width as far | ||
| 211 | * as EMIF is concerned is 32, where as the DDR bus width is 16 bits. | ||
| 212 | */ | ||
| 213 | static u32 get_emif_bus_width(struct emif_data *emif) | ||
| 214 | { | ||
| 215 | u32 width; | ||
| 216 | void __iomem *base = emif->base; | ||
| 217 | |||
| 218 | width = (readl(base + EMIF_SDRAM_CONFIG) & NARROW_MODE_MASK) | ||
| 219 | >> NARROW_MODE_SHIFT; | ||
| 220 | width = width == 0 ? 32 : 16; | ||
| 221 | |||
| 222 | return width; | ||
| 223 | } | ||
| 224 | |||
| 225 | /* | ||
| 226 | * Get the CL from SDRAM_CONFIG register | ||
| 227 | */ | ||
| 228 | static u32 get_cl(struct emif_data *emif) | ||
| 229 | { | ||
| 230 | u32 cl; | ||
| 231 | void __iomem *base = emif->base; | ||
| 232 | |||
| 233 | cl = (readl(base + EMIF_SDRAM_CONFIG) & CL_MASK) >> CL_SHIFT; | ||
| 234 | |||
| 235 | return cl; | ||
| 236 | } | ||
| 237 | |||
| 238 | static void set_lpmode(struct emif_data *emif, u8 lpmode) | ||
| 239 | { | ||
| 240 | u32 temp; | ||
| 241 | void __iomem *base = emif->base; | ||
| 242 | |||
| 243 | temp = readl(base + EMIF_POWER_MANAGEMENT_CONTROL); | ||
| 244 | temp &= ~LP_MODE_MASK; | ||
| 245 | temp |= (lpmode << LP_MODE_SHIFT); | ||
| 246 | writel(temp, base + EMIF_POWER_MANAGEMENT_CONTROL); | ||
| 247 | } | ||
| 248 | |||
| 249 | static void do_freq_update(void) | ||
| 250 | { | ||
| 251 | struct emif_data *emif; | ||
| 252 | |||
| 253 | /* | ||
| 254 | * Workaround for errata i728: Disable LPMODE during FREQ_UPDATE | ||
| 255 | * | ||
| 256 | * i728 DESCRIPTION: | ||
| 257 | * The EMIF automatically puts the SDRAM into self-refresh mode | ||
| 258 | * after the EMIF has not performed accesses during | ||
| 259 | * EMIF_PWR_MGMT_CTRL[7:4] REG_SR_TIM number of DDR clock cycles | ||
| 260 | * and the EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE bit field is set | ||
| 261 | * to 0x2. If during a small window the following three events | ||
| 262 | * occur: | ||
| 263 | * - The SR_TIMING counter expires | ||
| 264 | * - And frequency change is requested | ||
| 265 | * - And OCP access is requested | ||
| 266 | * Then it causes instable clock on the DDR interface. | ||
| 267 | * | ||
| 268 | * WORKAROUND | ||
| 269 | * To avoid the occurrence of the three events, the workaround | ||
| 270 | * is to disable the self-refresh when requesting a frequency | ||
| 271 | * change. Before requesting a frequency change the software must | ||
| 272 | * program EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE to 0x0. When the | ||
| 273 | * frequency change has been done, the software can reprogram | ||
| 274 | * EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE to 0x2 | ||
| 275 | */ | ||
| 276 | list_for_each_entry(emif, &device_list, node) { | ||
| 277 | if (emif->lpmode == EMIF_LP_MODE_SELF_REFRESH) | ||
| 278 | set_lpmode(emif, EMIF_LP_MODE_DISABLE); | ||
| 279 | } | ||
| 280 | |||
| 281 | /* | ||
| 282 | * TODO: Do FREQ_UPDATE here when an API | ||
| 283 | * is available for this as part of the new | ||
| 284 | * clock framework | ||
| 285 | */ | ||
| 286 | |||
| 287 | list_for_each_entry(emif, &device_list, node) { | ||
| 288 | if (emif->lpmode == EMIF_LP_MODE_SELF_REFRESH) | ||
| 289 | set_lpmode(emif, EMIF_LP_MODE_SELF_REFRESH); | ||
| 290 | } | ||
| 291 | } | ||
| 292 | |||
| 293 | /* Find addressing table entry based on the device's type and density */ | ||
| 294 | static const struct lpddr2_addressing *get_addressing_table( | ||
| 295 | const struct ddr_device_info *device_info) | ||
| 296 | { | ||
| 297 | u32 index, type, density; | ||
| 298 | |||
| 299 | type = device_info->type; | ||
| 300 | density = device_info->density; | ||
| 301 | |||
| 302 | switch (type) { | ||
| 303 | case DDR_TYPE_LPDDR2_S4: | ||
| 304 | index = density - 1; | ||
| 305 | break; | ||
| 306 | case DDR_TYPE_LPDDR2_S2: | ||
| 307 | switch (density) { | ||
| 308 | case DDR_DENSITY_1Gb: | ||
| 309 | case DDR_DENSITY_2Gb: | ||
| 310 | index = density + 3; | ||
| 311 | break; | ||
| 312 | default: | ||
| 313 | index = density - 1; | ||
| 314 | } | ||
| 315 | break; | ||
| 316 | default: | ||
| 317 | return NULL; | ||
| 318 | } | ||
| 319 | |||
| 320 | return &lpddr2_jedec_addressing_table[index]; | ||
| 321 | } | ||
| 322 | |||
| 323 | /* | ||
| 324 | * Find the the right timing table from the array of timing | ||
| 325 | * tables of the device using DDR clock frequency | ||
| 326 | */ | ||
| 327 | static const struct lpddr2_timings *get_timings_table(struct emif_data *emif, | ||
| 328 | u32 freq) | ||
| 329 | { | ||
| 330 | u32 i, min, max, freq_nearest; | ||
| 331 | const struct lpddr2_timings *timings = NULL; | ||
| 332 | const struct lpddr2_timings *timings_arr = emif->plat_data->timings; | ||
| 333 | struct device *dev = emif->dev; | ||
| 334 | |||
| 335 | /* Start with a very high frequency - 1GHz */ | ||
| 336 | freq_nearest = 1000000000; | ||
| 337 | |||
| 338 | /* | ||
| 339 | * Find the timings table such that: | ||
| 340 | * 1. the frequency range covers the required frequency(safe) AND | ||
| 341 | * 2. the max_freq is closest to the required frequency(optimal) | ||
| 342 | */ | ||
| 343 | for (i = 0; i < emif->plat_data->timings_arr_size; i++) { | ||
| 344 | max = timings_arr[i].max_freq; | ||
| 345 | min = timings_arr[i].min_freq; | ||
| 346 | if ((freq >= min) && (freq <= max) && (max < freq_nearest)) { | ||
| 347 | freq_nearest = max; | ||
| 348 | timings = &timings_arr[i]; | ||
| 349 | } | ||
| 350 | } | ||
| 351 | |||
| 352 | if (!timings) | ||
| 353 | dev_err(dev, "%s: couldn't find timings for - %dHz\n", | ||
| 354 | __func__, freq); | ||
| 355 | |||
| 356 | dev_dbg(dev, "%s: timings table: freq %d, speed bin freq %d\n", | ||
| 357 | __func__, freq, freq_nearest); | ||
| 358 | |||
| 359 | return timings; | ||
| 360 | } | ||
| 361 | |||
| 362 | static u32 get_sdram_ref_ctrl_shdw(u32 freq, | ||
| 363 | const struct lpddr2_addressing *addressing) | ||
| 364 | { | ||
| 365 | u32 ref_ctrl_shdw = 0, val = 0, freq_khz, t_refi; | ||
| 366 | |||
| 367 | /* Scale down frequency and t_refi to avoid overflow */ | ||
| 368 | freq_khz = freq / 1000; | ||
| 369 | t_refi = addressing->tREFI_ns / 100; | ||
| 370 | |||
| 371 | /* | ||
| 372 | * refresh rate to be set is 'tREFI(in us) * freq in MHz | ||
| 373 | * division by 10000 to account for change in units | ||
| 374 | */ | ||
| 375 | val = t_refi * freq_khz / 10000; | ||
| 376 | ref_ctrl_shdw |= val << REFRESH_RATE_SHIFT; | ||
| 377 | |||
| 378 | return ref_ctrl_shdw; | ||
| 379 | } | ||
| 380 | |||
| 381 | static u32 get_sdram_tim_1_shdw(const struct lpddr2_timings *timings, | ||
| 382 | const struct lpddr2_min_tck *min_tck, | ||
| 383 | const struct lpddr2_addressing *addressing) | ||
| 384 | { | ||
| 385 | u32 tim1 = 0, val = 0; | ||
| 386 | |||
| 387 | val = max(min_tck->tWTR, DIV_ROUND_UP(timings->tWTR, t_ck)) - 1; | ||
| 388 | tim1 |= val << T_WTR_SHIFT; | ||
| 389 | |||
| 390 | if (addressing->num_banks == B8) | ||
| 391 | val = DIV_ROUND_UP(timings->tFAW, t_ck*4); | ||
| 392 | else | ||
| 393 | val = max(min_tck->tRRD, DIV_ROUND_UP(timings->tRRD, t_ck)); | ||
| 394 | tim1 |= (val - 1) << T_RRD_SHIFT; | ||
| 395 | |||
| 396 | val = DIV_ROUND_UP(timings->tRAS_min + timings->tRPab, t_ck) - 1; | ||
| 397 | tim1 |= val << T_RC_SHIFT; | ||
| 398 | |||
| 399 | val = max(min_tck->tRASmin, DIV_ROUND_UP(timings->tRAS_min, t_ck)); | ||
| 400 | tim1 |= (val - 1) << T_RAS_SHIFT; | ||
| 401 | |||
| 402 | val = max(min_tck->tWR, DIV_ROUND_UP(timings->tWR, t_ck)) - 1; | ||
| 403 | tim1 |= val << T_WR_SHIFT; | ||
| 404 | |||
| 405 | val = max(min_tck->tRCD, DIV_ROUND_UP(timings->tRCD, t_ck)) - 1; | ||
| 406 | tim1 |= val << T_RCD_SHIFT; | ||
| 407 | |||
| 408 | val = max(min_tck->tRPab, DIV_ROUND_UP(timings->tRPab, t_ck)) - 1; | ||
| 409 | tim1 |= val << T_RP_SHIFT; | ||
| 410 | |||
| 411 | return tim1; | ||
| 412 | } | ||
| 413 | |||
| 414 | static u32 get_sdram_tim_1_shdw_derated(const struct lpddr2_timings *timings, | ||
| 415 | const struct lpddr2_min_tck *min_tck, | ||
| 416 | const struct lpddr2_addressing *addressing) | ||
| 417 | { | ||
| 418 | u32 tim1 = 0, val = 0; | ||
| 419 | |||
| 420 | val = max(min_tck->tWTR, DIV_ROUND_UP(timings->tWTR, t_ck)) - 1; | ||
| 421 | tim1 = val << T_WTR_SHIFT; | ||
| 422 | |||
| 423 | /* | ||
| 424 | * tFAW is approximately 4 times tRRD. So add 1875*4 = 7500ps | ||
| 425 | * to tFAW for de-rating | ||
| 426 | */ | ||
| 427 | if (addressing->num_banks == B8) { | ||
| 428 | val = DIV_ROUND_UP(timings->tFAW + 7500, 4 * t_ck) - 1; | ||
| 429 | } else { | ||
| 430 | val = DIV_ROUND_UP(timings->tRRD + 1875, t_ck); | ||
| 431 | val = max(min_tck->tRRD, val) - 1; | ||
| 432 | } | ||
| 433 | tim1 |= val << T_RRD_SHIFT; | ||
| 434 | |||
| 435 | val = DIV_ROUND_UP(timings->tRAS_min + timings->tRPab + 1875, t_ck); | ||
| 436 | tim1 |= (val - 1) << T_RC_SHIFT; | ||
| 437 | |||
| 438 | val = DIV_ROUND_UP(timings->tRAS_min + 1875, t_ck); | ||
| 439 | val = max(min_tck->tRASmin, val) - 1; | ||
| 440 | tim1 |= val << T_RAS_SHIFT; | ||
| 441 | |||
| 442 | val = max(min_tck->tWR, DIV_ROUND_UP(timings->tWR, t_ck)) - 1; | ||
| 443 | tim1 |= val << T_WR_SHIFT; | ||
| 444 | |||
| 445 | val = max(min_tck->tRCD, DIV_ROUND_UP(timings->tRCD + 1875, t_ck)); | ||
| 446 | tim1 |= (val - 1) << T_RCD_SHIFT; | ||
| 447 | |||
| 448 | val = max(min_tck->tRPab, DIV_ROUND_UP(timings->tRPab + 1875, t_ck)); | ||
| 449 | tim1 |= (val - 1) << T_RP_SHIFT; | ||
| 450 | |||
| 451 | return tim1; | ||
| 452 | } | ||
| 453 | |||
| 454 | static u32 get_sdram_tim_2_shdw(const struct lpddr2_timings *timings, | ||
| 455 | const struct lpddr2_min_tck *min_tck, | ||
| 456 | const struct lpddr2_addressing *addressing, | ||
| 457 | u32 type) | ||
| 458 | { | ||
| 459 | u32 tim2 = 0, val = 0; | ||
| 460 | |||
| 461 | val = min_tck->tCKE - 1; | ||
| 462 | tim2 |= val << T_CKE_SHIFT; | ||
| 463 | |||
| 464 | val = max(min_tck->tRTP, DIV_ROUND_UP(timings->tRTP, t_ck)) - 1; | ||
| 465 | tim2 |= val << T_RTP_SHIFT; | ||
| 466 | |||
| 467 | /* tXSNR = tRFCab_ps + 10 ns(tRFCab_ps for LPDDR2). */ | ||
| 468 | val = DIV_ROUND_UP(addressing->tRFCab_ps + 10000, t_ck) - 1; | ||
| 469 | tim2 |= val << T_XSNR_SHIFT; | ||
| 470 | |||
| 471 | /* XSRD same as XSNR for LPDDR2 */ | ||
| 472 | tim2 |= val << T_XSRD_SHIFT; | ||
| 473 | |||
| 474 | val = max(min_tck->tXP, DIV_ROUND_UP(timings->tXP, t_ck)) - 1; | ||
| 475 | tim2 |= val << T_XP_SHIFT; | ||
| 476 | |||
| 477 | return tim2; | ||
| 478 | } | ||
| 479 | |||
| 480 | static u32 get_sdram_tim_3_shdw(const struct lpddr2_timings *timings, | ||
| 481 | const struct lpddr2_min_tck *min_tck, | ||
| 482 | const struct lpddr2_addressing *addressing, | ||
| 483 | u32 type, u32 ip_rev, u32 derated) | ||
| 484 | { | ||
| 485 | u32 tim3 = 0, val = 0, t_dqsck; | ||
| 486 | |||
| 487 | val = timings->tRAS_max_ns / addressing->tREFI_ns - 1; | ||
| 488 | val = val > 0xF ? 0xF : val; | ||
| 489 | tim3 |= val << T_RAS_MAX_SHIFT; | ||
| 490 | |||
| 491 | val = DIV_ROUND_UP(addressing->tRFCab_ps, t_ck) - 1; | ||
| 492 | tim3 |= val << T_RFC_SHIFT; | ||
| 493 | |||
| 494 | t_dqsck = (derated == EMIF_DERATED_TIMINGS) ? | ||
| 495 | timings->tDQSCK_max_derated : timings->tDQSCK_max; | ||
| 496 | if (ip_rev == EMIF_4D5) | ||
| 497 | val = DIV_ROUND_UP(t_dqsck + 1000, t_ck) - 1; | ||
| 498 | else | ||
| 499 | val = DIV_ROUND_UP(t_dqsck, t_ck) - 1; | ||
| 500 | |||
| 501 | tim3 |= val << T_TDQSCKMAX_SHIFT; | ||
| 502 | |||
| 503 | val = DIV_ROUND_UP(timings->tZQCS, t_ck) - 1; | ||
| 504 | tim3 |= val << ZQ_ZQCS_SHIFT; | ||
| 505 | |||
| 506 | val = DIV_ROUND_UP(timings->tCKESR, t_ck); | ||
| 507 | val = max(min_tck->tCKESR, val) - 1; | ||
| 508 | tim3 |= val << T_CKESR_SHIFT; | ||
| 509 | |||
| 510 | if (ip_rev == EMIF_4D5) { | ||
| 511 | tim3 |= (EMIF_T_CSTA - 1) << T_CSTA_SHIFT; | ||
| 512 | |||
| 513 | val = DIV_ROUND_UP(EMIF_T_PDLL_UL, 128) - 1; | ||
| 514 | tim3 |= val << T_PDLL_UL_SHIFT; | ||
| 515 | } | ||
| 516 | |||
| 517 | return tim3; | ||
| 518 | } | ||
| 519 | |||
| 520 | static u32 get_zq_config_reg(const struct lpddr2_addressing *addressing, | ||
| 521 | bool cs1_used, bool cal_resistors_per_cs) | ||
| 522 | { | ||
| 523 | u32 zq = 0, val = 0; | ||
| 524 | |||
| 525 | val = EMIF_ZQCS_INTERVAL_US * 1000 / addressing->tREFI_ns; | ||
| 526 | zq |= val << ZQ_REFINTERVAL_SHIFT; | ||
| 527 | |||
| 528 | val = DIV_ROUND_UP(T_ZQCL_DEFAULT_NS, T_ZQCS_DEFAULT_NS) - 1; | ||
| 529 | zq |= val << ZQ_ZQCL_MULT_SHIFT; | ||
| 530 | |||
| 531 | val = DIV_ROUND_UP(T_ZQINIT_DEFAULT_NS, T_ZQCL_DEFAULT_NS) - 1; | ||
| 532 | zq |= val << ZQ_ZQINIT_MULT_SHIFT; | ||
| 533 | |||
| 534 | zq |= ZQ_SFEXITEN_ENABLE << ZQ_SFEXITEN_SHIFT; | ||
| 535 | |||
| 536 | if (cal_resistors_per_cs) | ||
| 537 | zq |= ZQ_DUALCALEN_ENABLE << ZQ_DUALCALEN_SHIFT; | ||
| 538 | else | ||
| 539 | zq |= ZQ_DUALCALEN_DISABLE << ZQ_DUALCALEN_SHIFT; | ||
| 540 | |||
| 541 | zq |= ZQ_CS0EN_MASK; /* CS0 is used for sure */ | ||
| 542 | |||
| 543 | val = cs1_used ? 1 : 0; | ||
| 544 | zq |= val << ZQ_CS1EN_SHIFT; | ||
| 545 | |||
| 546 | return zq; | ||
| 547 | } | ||
| 548 | |||
| 549 | static u32 get_temp_alert_config(const struct lpddr2_addressing *addressing, | ||
| 550 | const struct emif_custom_configs *custom_configs, bool cs1_used, | ||
| 551 | u32 sdram_io_width, u32 emif_bus_width) | ||
| 552 | { | ||
| 553 | u32 alert = 0, interval, devcnt; | ||
| 554 | |||
| 555 | if (custom_configs && (custom_configs->mask & | ||
| 556 | EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL)) | ||
| 557 | interval = custom_configs->temp_alert_poll_interval_ms; | ||
| 558 | else | ||
| 559 | interval = TEMP_ALERT_POLL_INTERVAL_DEFAULT_MS; | ||
| 560 | |||
| 561 | interval *= 1000000; /* Convert to ns */ | ||
| 562 | interval /= addressing->tREFI_ns; /* Convert to refresh cycles */ | ||
| 563 | alert |= (interval << TA_REFINTERVAL_SHIFT); | ||
| 564 | |||
| 565 | /* | ||
| 566 | * sdram_io_width is in 'log2(x) - 1' form. Convert emif_bus_width | ||
| 567 | * also to this form and subtract to get TA_DEVCNT, which is | ||
| 568 | * in log2(x) form. | ||
| 569 | */ | ||
| 570 | emif_bus_width = __fls(emif_bus_width) - 1; | ||
| 571 | devcnt = emif_bus_width - sdram_io_width; | ||
| 572 | alert |= devcnt << TA_DEVCNT_SHIFT; | ||
| 573 | |||
| 574 | /* DEVWDT is in 'log2(x) - 3' form */ | ||
| 575 | alert |= (sdram_io_width - 2) << TA_DEVWDT_SHIFT; | ||
| 576 | |||
| 577 | alert |= 1 << TA_SFEXITEN_SHIFT; | ||
| 578 | alert |= 1 << TA_CS0EN_SHIFT; | ||
| 579 | alert |= (cs1_used ? 1 : 0) << TA_CS1EN_SHIFT; | ||
| 580 | |||
| 581 | return alert; | ||
| 582 | } | ||
| 583 | |||
| 584 | static u32 get_read_idle_ctrl_shdw(u8 volt_ramp) | ||
| 585 | { | ||
| 586 | u32 idle = 0, val = 0; | ||
| 587 | |||
| 588 | /* | ||
| 589 | * Maximum value in normal conditions and increased frequency | ||
| 590 | * when voltage is ramping | ||
| 591 | */ | ||
| 592 | if (volt_ramp) | ||
| 593 | val = READ_IDLE_INTERVAL_DVFS / t_ck / 64 - 1; | ||
| 594 | else | ||
| 595 | val = 0x1FF; | ||
| 596 | |||
| 597 | /* | ||
| 598 | * READ_IDLE_CTRL register in EMIF4D has same offset and fields | ||
| 599 | * as DLL_CALIB_CTRL in EMIF4D5, so use the same shifts | ||
| 600 | */ | ||
| 601 | idle |= val << DLL_CALIB_INTERVAL_SHIFT; | ||
| 602 | idle |= EMIF_READ_IDLE_LEN_VAL << ACK_WAIT_SHIFT; | ||
| 603 | |||
| 604 | return idle; | ||
| 605 | } | ||
| 606 | |||
| 607 | static u32 get_dll_calib_ctrl_shdw(u8 volt_ramp) | ||
| 608 | { | ||
| 609 | u32 calib = 0, val = 0; | ||
| 610 | |||
| 611 | if (volt_ramp == DDR_VOLTAGE_RAMPING) | ||
| 612 | val = DLL_CALIB_INTERVAL_DVFS / t_ck / 16 - 1; | ||
| 613 | else | ||
| 614 | val = 0; /* Disabled when voltage is stable */ | ||
| 615 | |||
| 616 | calib |= val << DLL_CALIB_INTERVAL_SHIFT; | ||
| 617 | calib |= DLL_CALIB_ACK_WAIT_VAL << ACK_WAIT_SHIFT; | ||
| 618 | |||
| 619 | return calib; | ||
| 620 | } | ||
| 621 | |||
| 622 | static u32 get_ddr_phy_ctrl_1_attilaphy_4d(const struct lpddr2_timings *timings, | ||
| 623 | u32 freq, u8 RL) | ||
| 624 | { | ||
| 625 | u32 phy = EMIF_DDR_PHY_CTRL_1_BASE_VAL_ATTILAPHY, val = 0; | ||
| 626 | |||
| 627 | val = RL + DIV_ROUND_UP(timings->tDQSCK_max, t_ck) - 1; | ||
| 628 | phy |= val << READ_LATENCY_SHIFT_4D; | ||
| 629 | |||
| 630 | if (freq <= 100000000) | ||
| 631 | val = EMIF_DLL_SLAVE_DLY_CTRL_100_MHZ_AND_LESS_ATTILAPHY; | ||
| 632 | else if (freq <= 200000000) | ||
| 633 | val = EMIF_DLL_SLAVE_DLY_CTRL_200_MHZ_ATTILAPHY; | ||
| 634 | else | ||
| 635 | val = EMIF_DLL_SLAVE_DLY_CTRL_400_MHZ_ATTILAPHY; | ||
| 636 | |||
| 637 | phy |= val << DLL_SLAVE_DLY_CTRL_SHIFT_4D; | ||
| 638 | |||
| 639 | return phy; | ||
| 640 | } | ||
| 641 | |||
| 642 | static u32 get_phy_ctrl_1_intelliphy_4d5(u32 freq, u8 cl) | ||
| 643 | { | ||
| 644 | u32 phy = EMIF_DDR_PHY_CTRL_1_BASE_VAL_INTELLIPHY, half_delay; | ||
| 645 | |||
| 646 | /* | ||
| 647 | * DLL operates at 266 MHz. If DDR frequency is near 266 MHz, | ||
| 648 | * half-delay is not needed else set half-delay | ||
| 649 | */ | ||
| 650 | if (freq >= 265000000 && freq < 267000000) | ||
| 651 | half_delay = 0; | ||
| 652 | else | ||
| 653 | half_delay = 1; | ||
| 654 | |||
| 655 | phy |= half_delay << DLL_HALF_DELAY_SHIFT_4D5; | ||
| 656 | phy |= ((cl + DIV_ROUND_UP(EMIF_PHY_TOTAL_READ_LATENCY_INTELLIPHY_PS, | ||
| 657 | t_ck) - 1) << READ_LATENCY_SHIFT_4D5); | ||
| 658 | |||
| 659 | return phy; | ||
| 660 | } | ||
| 661 | |||
| 662 | static u32 get_ext_phy_ctrl_2_intelliphy_4d5(void) | ||
| 663 | { | ||
| 664 | u32 fifo_we_slave_ratio; | ||
| 665 | |||
| 666 | fifo_we_slave_ratio = DIV_ROUND_CLOSEST( | ||
| 667 | EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS * 256 , t_ck); | ||
| 668 | |||
| 669 | return fifo_we_slave_ratio | fifo_we_slave_ratio << 11 | | ||
| 670 | fifo_we_slave_ratio << 22; | ||
| 671 | } | ||
| 672 | |||
| 673 | static u32 get_ext_phy_ctrl_3_intelliphy_4d5(void) | ||
| 674 | { | ||
| 675 | u32 fifo_we_slave_ratio; | ||
| 676 | |||
| 677 | fifo_we_slave_ratio = DIV_ROUND_CLOSEST( | ||
| 678 | EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS * 256 , t_ck); | ||
| 679 | |||
| 680 | return fifo_we_slave_ratio >> 10 | fifo_we_slave_ratio << 1 | | ||
| 681 | fifo_we_slave_ratio << 12 | fifo_we_slave_ratio << 23; | ||
| 682 | } | ||
| 683 | |||
| 684 | static u32 get_ext_phy_ctrl_4_intelliphy_4d5(void) | ||
| 685 | { | ||
| 686 | u32 fifo_we_slave_ratio; | ||
| 687 | |||
| 688 | fifo_we_slave_ratio = DIV_ROUND_CLOSEST( | ||
| 689 | EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS * 256 , t_ck); | ||
| 690 | |||
| 691 | return fifo_we_slave_ratio >> 9 | fifo_we_slave_ratio << 2 | | ||
| 692 | fifo_we_slave_ratio << 13; | ||
| 693 | } | ||
| 694 | |||
| 695 | static u32 get_pwr_mgmt_ctrl(u32 freq, struct emif_data *emif, u32 ip_rev) | ||
| 696 | { | ||
| 697 | u32 pwr_mgmt_ctrl = 0, timeout; | ||
| 698 | u32 lpmode = EMIF_LP_MODE_SELF_REFRESH; | ||
| 699 | u32 timeout_perf = EMIF_LP_MODE_TIMEOUT_PERFORMANCE; | ||
| 700 | u32 timeout_pwr = EMIF_LP_MODE_TIMEOUT_POWER; | ||
| 701 | u32 freq_threshold = EMIF_LP_MODE_FREQ_THRESHOLD; | ||
| 702 | |||
| 703 | struct emif_custom_configs *cust_cfgs = emif->plat_data->custom_configs; | ||
| 704 | |||
| 705 | if (cust_cfgs && (cust_cfgs->mask & EMIF_CUSTOM_CONFIG_LPMODE)) { | ||
| 706 | lpmode = cust_cfgs->lpmode; | ||
| 707 | timeout_perf = cust_cfgs->lpmode_timeout_performance; | ||
| 708 | timeout_pwr = cust_cfgs->lpmode_timeout_power; | ||
| 709 | freq_threshold = cust_cfgs->lpmode_freq_threshold; | ||
| 710 | } | ||
| 711 | |||
| 712 | /* Timeout based on DDR frequency */ | ||
| 713 | timeout = freq >= freq_threshold ? timeout_perf : timeout_pwr; | ||
| 714 | |||
| 715 | /* The value to be set in register is "log2(timeout) - 3" */ | ||
| 716 | if (timeout < 16) { | ||
| 717 | timeout = 0; | ||
| 718 | } else { | ||
| 719 | timeout = __fls(timeout) - 3; | ||
| 720 | if (timeout & (timeout - 1)) | ||
| 721 | timeout++; | ||
| 722 | } | ||
| 723 | |||
| 724 | switch (lpmode) { | ||
| 725 | case EMIF_LP_MODE_CLOCK_STOP: | ||
| 726 | pwr_mgmt_ctrl = (timeout << CS_TIM_SHIFT) | | ||
| 727 | SR_TIM_MASK | PD_TIM_MASK; | ||
| 728 | break; | ||
| 729 | case EMIF_LP_MODE_SELF_REFRESH: | ||
| 730 | /* Workaround for errata i735 */ | ||
| 731 | if (timeout < 6) | ||
| 732 | timeout = 6; | ||
| 733 | |||
| 734 | pwr_mgmt_ctrl = (timeout << SR_TIM_SHIFT) | | ||
| 735 | CS_TIM_MASK | PD_TIM_MASK; | ||
| 736 | break; | ||
| 737 | case EMIF_LP_MODE_PWR_DN: | ||
| 738 | pwr_mgmt_ctrl = (timeout << PD_TIM_SHIFT) | | ||
| 739 | CS_TIM_MASK | SR_TIM_MASK; | ||
| 740 | break; | ||
| 741 | case EMIF_LP_MODE_DISABLE: | ||
| 742 | default: | ||
| 743 | pwr_mgmt_ctrl = CS_TIM_MASK | | ||
| 744 | PD_TIM_MASK | SR_TIM_MASK; | ||
| 745 | } | ||
| 746 | |||
| 747 | /* No CS_TIM in EMIF_4D5 */ | ||
| 748 | if (ip_rev == EMIF_4D5) | ||
| 749 | pwr_mgmt_ctrl &= ~CS_TIM_MASK; | ||
| 750 | |||
| 751 | pwr_mgmt_ctrl |= lpmode << LP_MODE_SHIFT; | ||
| 752 | |||
| 753 | return pwr_mgmt_ctrl; | ||
| 754 | } | ||
| 755 | |||
| 756 | /* | ||
| 757 | * Get the temperature level of the EMIF instance: | ||
| 758 | * Reads the MR4 register of attached SDRAM parts to find out the temperature | ||
| 759 | * level. If there are two parts attached(one on each CS), then the temperature | ||
| 760 | * level for the EMIF instance is the higher of the two temperatures. | ||
| 761 | */ | ||
| 762 | static void get_temperature_level(struct emif_data *emif) | ||
| 763 | { | ||
| 764 | u32 temp, temperature_level; | ||
| 765 | void __iomem *base; | ||
| 766 | |||
| 767 | base = emif->base; | ||
| 768 | |||
| 769 | /* Read mode register 4 */ | ||
| 770 | writel(DDR_MR4, base + EMIF_LPDDR2_MODE_REG_CONFIG); | ||
| 771 | temperature_level = readl(base + EMIF_LPDDR2_MODE_REG_DATA); | ||
| 772 | temperature_level = (temperature_level & MR4_SDRAM_REF_RATE_MASK) >> | ||
| 773 | MR4_SDRAM_REF_RATE_SHIFT; | ||
| 774 | |||
| 775 | if (emif->plat_data->device_info->cs1_used) { | ||
| 776 | writel(DDR_MR4 | CS_MASK, base + EMIF_LPDDR2_MODE_REG_CONFIG); | ||
| 777 | temp = readl(base + EMIF_LPDDR2_MODE_REG_DATA); | ||
| 778 | temp = (temp & MR4_SDRAM_REF_RATE_MASK) | ||
| 779 | >> MR4_SDRAM_REF_RATE_SHIFT; | ||
| 780 | temperature_level = max(temp, temperature_level); | ||
| 781 | } | ||
| 782 | |||
| 783 | /* treat everything less than nominal(3) in MR4 as nominal */ | ||
| 784 | if (unlikely(temperature_level < SDRAM_TEMP_NOMINAL)) | ||
| 785 | temperature_level = SDRAM_TEMP_NOMINAL; | ||
| 786 | |||
| 787 | /* if we get reserved value in MR4 persist with the existing value */ | ||
| 788 | if (likely(temperature_level != SDRAM_TEMP_RESERVED_4)) | ||
| 789 | emif->temperature_level = temperature_level; | ||
| 790 | } | ||
| 791 | |||
| 792 | /* | ||
| 793 | * Program EMIF shadow registers that are not dependent on temperature | ||
| 794 | * or voltage | ||
| 795 | */ | ||
| 796 | static void setup_registers(struct emif_data *emif, struct emif_regs *regs) | ||
| 797 | { | ||
| 798 | void __iomem *base = emif->base; | ||
| 799 | |||
| 800 | writel(regs->sdram_tim2_shdw, base + EMIF_SDRAM_TIMING_2_SHDW); | ||
| 801 | writel(regs->phy_ctrl_1_shdw, base + EMIF_DDR_PHY_CTRL_1_SHDW); | ||
| 802 | |||
| 803 | /* Settings specific for EMIF4D5 */ | ||
| 804 | if (emif->plat_data->ip_rev != EMIF_4D5) | ||
| 805 | return; | ||
| 806 | writel(regs->ext_phy_ctrl_2_shdw, base + EMIF_EXT_PHY_CTRL_2_SHDW); | ||
| 807 | writel(regs->ext_phy_ctrl_3_shdw, base + EMIF_EXT_PHY_CTRL_3_SHDW); | ||
| 808 | writel(regs->ext_phy_ctrl_4_shdw, base + EMIF_EXT_PHY_CTRL_4_SHDW); | ||
| 809 | } | ||
| 810 | |||
| 811 | /* | ||
| 812 | * When voltage ramps dll calibration and forced read idle should | ||
| 813 | * happen more often | ||
| 814 | */ | ||
| 815 | static void setup_volt_sensitive_regs(struct emif_data *emif, | ||
| 816 | struct emif_regs *regs, u32 volt_state) | ||
| 817 | { | ||
| 818 | u32 calib_ctrl; | ||
| 819 | void __iomem *base = emif->base; | ||
| 820 | |||
| 821 | /* | ||
| 822 | * EMIF_READ_IDLE_CTRL in EMIF4D refers to the same register as | ||
| 823 | * EMIF_DLL_CALIB_CTRL in EMIF4D5 and dll_calib_ctrl_shadow_* | ||
| 824 | * is an alias of the respective read_idle_ctrl_shdw_* (members of | ||
| 825 | * a union). So, the below code takes care of both cases | ||
| 826 | */ | ||
| 827 | if (volt_state == DDR_VOLTAGE_RAMPING) | ||
| 828 | calib_ctrl = regs->dll_calib_ctrl_shdw_volt_ramp; | ||
| 829 | else | ||
| 830 | calib_ctrl = regs->dll_calib_ctrl_shdw_normal; | ||
| 831 | |||
| 832 | writel(calib_ctrl, base + EMIF_DLL_CALIB_CTRL_SHDW); | ||
| 833 | } | ||
| 834 | |||
| 835 | /* | ||
| 836 | * setup_temperature_sensitive_regs() - set the timings for temperature | ||
| 837 | * sensitive registers. This happens once at initialisation time based | ||
| 838 | * on the temperature at boot time and subsequently based on the temperature | ||
| 839 | * alert interrupt. Temperature alert can happen when the temperature | ||
| 840 | * increases or drops. So this function can have the effect of either | ||
| 841 | * derating the timings or going back to nominal values. | ||
| 842 | */ | ||
| 843 | static void setup_temperature_sensitive_regs(struct emif_data *emif, | ||
| 844 | struct emif_regs *regs) | ||
| 845 | { | ||
| 846 | u32 tim1, tim3, ref_ctrl, type; | ||
| 847 | void __iomem *base = emif->base; | ||
| 848 | u32 temperature; | ||
| 849 | |||
| 850 | type = emif->plat_data->device_info->type; | ||
| 851 | |||
| 852 | tim1 = regs->sdram_tim1_shdw; | ||
| 853 | tim3 = regs->sdram_tim3_shdw; | ||
| 854 | ref_ctrl = regs->ref_ctrl_shdw; | ||
| 855 | |||
| 856 | /* No de-rating for non-lpddr2 devices */ | ||
| 857 | if (type != DDR_TYPE_LPDDR2_S2 && type != DDR_TYPE_LPDDR2_S4) | ||
| 858 | goto out; | ||
| 859 | |||
| 860 | temperature = emif->temperature_level; | ||
| 861 | if (temperature == SDRAM_TEMP_HIGH_DERATE_REFRESH) { | ||
| 862 | ref_ctrl = regs->ref_ctrl_shdw_derated; | ||
| 863 | } else if (temperature == SDRAM_TEMP_HIGH_DERATE_REFRESH_AND_TIMINGS) { | ||
| 864 | tim1 = regs->sdram_tim1_shdw_derated; | ||
| 865 | tim3 = regs->sdram_tim3_shdw_derated; | ||
| 866 | ref_ctrl = regs->ref_ctrl_shdw_derated; | ||
| 867 | } | ||
| 868 | |||
| 869 | out: | ||
| 870 | writel(tim1, base + EMIF_SDRAM_TIMING_1_SHDW); | ||
| 871 | writel(tim3, base + EMIF_SDRAM_TIMING_3_SHDW); | ||
| 872 | writel(ref_ctrl, base + EMIF_SDRAM_REFRESH_CTRL_SHDW); | ||
| 873 | } | ||
| 874 | |||
| 875 | static irqreturn_t handle_temp_alert(void __iomem *base, struct emif_data *emif) | ||
| 876 | { | ||
| 877 | u32 old_temp_level; | ||
| 878 | irqreturn_t ret = IRQ_HANDLED; | ||
| 879 | |||
| 880 | spin_lock_irqsave(&emif_lock, irq_state); | ||
| 881 | old_temp_level = emif->temperature_level; | ||
| 882 | get_temperature_level(emif); | ||
| 883 | |||
| 884 | if (unlikely(emif->temperature_level == old_temp_level)) { | ||
| 885 | goto out; | ||
| 886 | } else if (!emif->curr_regs) { | ||
| 887 | dev_err(emif->dev, "temperature alert before registers are calculated, not de-rating timings\n"); | ||
| 888 | goto out; | ||
| 889 | } | ||
| 890 | |||
| 891 | if (emif->temperature_level < old_temp_level || | ||
| 892 | emif->temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN) { | ||
| 893 | /* | ||
| 894 | * Temperature coming down - defer handling to thread OR | ||
| 895 | * Temperature far too high - do kernel_power_off() from | ||
| 896 | * thread context | ||
| 897 | */ | ||
| 898 | ret = IRQ_WAKE_THREAD; | ||
| 899 | } else { | ||
| 900 | /* Temperature is going up - handle immediately */ | ||
| 901 | setup_temperature_sensitive_regs(emif, emif->curr_regs); | ||
| 902 | do_freq_update(); | ||
| 903 | } | ||
| 904 | |||
| 905 | out: | ||
| 906 | spin_unlock_irqrestore(&emif_lock, irq_state); | ||
| 907 | return ret; | ||
| 908 | } | ||
| 909 | |||
| 910 | static irqreturn_t emif_interrupt_handler(int irq, void *dev_id) | ||
| 911 | { | ||
| 912 | u32 interrupts; | ||
| 913 | struct emif_data *emif = dev_id; | ||
| 914 | void __iomem *base = emif->base; | ||
| 915 | struct device *dev = emif->dev; | ||
| 916 | irqreturn_t ret = IRQ_HANDLED; | ||
| 917 | |||
| 918 | /* Save the status and clear it */ | ||
| 919 | interrupts = readl(base + EMIF_SYSTEM_OCP_INTERRUPT_STATUS); | ||
| 920 | writel(interrupts, base + EMIF_SYSTEM_OCP_INTERRUPT_STATUS); | ||
| 921 | |||
| 922 | /* | ||
| 923 | * Handle temperature alert | ||
| 924 | * Temperature alert should be same for all ports | ||
| 925 | * So, it's enough to process it only for one of the ports | ||
| 926 | */ | ||
| 927 | if (interrupts & TA_SYS_MASK) | ||
| 928 | ret = handle_temp_alert(base, emif); | ||
| 929 | |||
| 930 | if (interrupts & ERR_SYS_MASK) | ||
| 931 | dev_err(dev, "Access error from SYS port - %x\n", interrupts); | ||
| 932 | |||
| 933 | if (emif->plat_data->hw_caps & EMIF_HW_CAPS_LL_INTERFACE) { | ||
| 934 | /* Save the status and clear it */ | ||
| 935 | interrupts = readl(base + EMIF_LL_OCP_INTERRUPT_STATUS); | ||
| 936 | writel(interrupts, base + EMIF_LL_OCP_INTERRUPT_STATUS); | ||
| 937 | |||
| 938 | if (interrupts & ERR_LL_MASK) | ||
| 939 | dev_err(dev, "Access error from LL port - %x\n", | ||
| 940 | interrupts); | ||
| 941 | } | ||
| 942 | |||
| 943 | return ret; | ||
| 944 | } | ||
| 945 | |||
| 946 | static irqreturn_t emif_threaded_isr(int irq, void *dev_id) | ||
| 947 | { | ||
| 948 | struct emif_data *emif = dev_id; | ||
| 949 | |||
| 950 | if (emif->temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN) { | ||
| 951 | dev_emerg(emif->dev, "SDRAM temperature exceeds operating limit.. Needs shut down!!!\n"); | ||
| 952 | kernel_power_off(); | ||
| 953 | return IRQ_HANDLED; | ||
| 954 | } | ||
| 955 | |||
| 956 | spin_lock_irqsave(&emif_lock, irq_state); | ||
| 957 | |||
| 958 | if (emif->curr_regs) { | ||
| 959 | setup_temperature_sensitive_regs(emif, emif->curr_regs); | ||
| 960 | do_freq_update(); | ||
| 961 | } else { | ||
| 962 | dev_err(emif->dev, "temperature alert before registers are calculated, not de-rating timings\n"); | ||
| 963 | } | ||
| 964 | |||
| 965 | spin_unlock_irqrestore(&emif_lock, irq_state); | ||
| 966 | |||
| 967 | return IRQ_HANDLED; | ||
| 968 | } | ||
| 969 | |||
| 970 | static void clear_all_interrupts(struct emif_data *emif) | ||
| 971 | { | ||
| 972 | void __iomem *base = emif->base; | ||
| 973 | |||
| 974 | writel(readl(base + EMIF_SYSTEM_OCP_INTERRUPT_STATUS), | ||
| 975 | base + EMIF_SYSTEM_OCP_INTERRUPT_STATUS); | ||
| 976 | if (emif->plat_data->hw_caps & EMIF_HW_CAPS_LL_INTERFACE) | ||
| 977 | writel(readl(base + EMIF_LL_OCP_INTERRUPT_STATUS), | ||
| 978 | base + EMIF_LL_OCP_INTERRUPT_STATUS); | ||
| 979 | } | ||
| 980 | |||
| 981 | static void disable_and_clear_all_interrupts(struct emif_data *emif) | ||
| 982 | { | ||
| 983 | void __iomem *base = emif->base; | ||
| 984 | |||
| 985 | /* Disable all interrupts */ | ||
| 986 | writel(readl(base + EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET), | ||
| 987 | base + EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_CLEAR); | ||
| 988 | if (emif->plat_data->hw_caps & EMIF_HW_CAPS_LL_INTERFACE) | ||
| 989 | writel(readl(base + EMIF_LL_OCP_INTERRUPT_ENABLE_SET), | ||
| 990 | base + EMIF_LL_OCP_INTERRUPT_ENABLE_CLEAR); | ||
| 991 | |||
| 992 | /* Clear all interrupts */ | ||
| 993 | clear_all_interrupts(emif); | ||
| 994 | } | ||
| 995 | |||
| 996 | static int __init_or_module setup_interrupts(struct emif_data *emif, u32 irq) | ||
| 997 | { | ||
| 998 | u32 interrupts, type; | ||
| 999 | void __iomem *base = emif->base; | ||
| 1000 | |||
| 1001 | type = emif->plat_data->device_info->type; | ||
| 1002 | |||
| 1003 | clear_all_interrupts(emif); | ||
| 1004 | |||
| 1005 | /* Enable interrupts for SYS interface */ | ||
| 1006 | interrupts = EN_ERR_SYS_MASK; | ||
| 1007 | if (type == DDR_TYPE_LPDDR2_S2 || type == DDR_TYPE_LPDDR2_S4) | ||
| 1008 | interrupts |= EN_TA_SYS_MASK; | ||
| 1009 | writel(interrupts, base + EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET); | ||
| 1010 | |||
| 1011 | /* Enable interrupts for LL interface */ | ||
| 1012 | if (emif->plat_data->hw_caps & EMIF_HW_CAPS_LL_INTERFACE) { | ||
| 1013 | /* TA need not be enabled for LL */ | ||
| 1014 | interrupts = EN_ERR_LL_MASK; | ||
| 1015 | writel(interrupts, base + EMIF_LL_OCP_INTERRUPT_ENABLE_SET); | ||
| 1016 | } | ||
| 1017 | |||
| 1018 | /* setup IRQ handlers */ | ||
| 1019 | return devm_request_threaded_irq(emif->dev, irq, | ||
| 1020 | emif_interrupt_handler, | ||
| 1021 | emif_threaded_isr, | ||
| 1022 | 0, dev_name(emif->dev), | ||
| 1023 | emif); | ||
| 1024 | |||
| 1025 | } | ||
| 1026 | |||
| 1027 | static void __init_or_module emif_onetime_settings(struct emif_data *emif) | ||
| 1028 | { | ||
| 1029 | u32 pwr_mgmt_ctrl, zq, temp_alert_cfg; | ||
| 1030 | void __iomem *base = emif->base; | ||
| 1031 | const struct lpddr2_addressing *addressing; | ||
| 1032 | const struct ddr_device_info *device_info; | ||
| 1033 | |||
| 1034 | device_info = emif->plat_data->device_info; | ||
| 1035 | addressing = get_addressing_table(device_info); | ||
| 1036 | |||
| 1037 | /* | ||
| 1038 | * Init power management settings | ||
| 1039 | * We don't know the frequency yet. Use a high frequency | ||
| 1040 | * value for a conservative timeout setting | ||
| 1041 | */ | ||
| 1042 | pwr_mgmt_ctrl = get_pwr_mgmt_ctrl(1000000000, emif, | ||
| 1043 | emif->plat_data->ip_rev); | ||
| 1044 | emif->lpmode = (pwr_mgmt_ctrl & LP_MODE_MASK) >> LP_MODE_SHIFT; | ||
| 1045 | writel(pwr_mgmt_ctrl, base + EMIF_POWER_MANAGEMENT_CONTROL); | ||
| 1046 | |||
| 1047 | /* Init ZQ calibration settings */ | ||
| 1048 | zq = get_zq_config_reg(addressing, device_info->cs1_used, | ||
| 1049 | device_info->cal_resistors_per_cs); | ||
| 1050 | writel(zq, base + EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG); | ||
| 1051 | |||
| 1052 | /* Check temperature level temperature level*/ | ||
| 1053 | get_temperature_level(emif); | ||
| 1054 | if (emif->temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN) | ||
| 1055 | dev_emerg(emif->dev, "SDRAM temperature exceeds operating limit.. Needs shut down!!!\n"); | ||
| 1056 | |||
| 1057 | /* Init temperature polling */ | ||
| 1058 | temp_alert_cfg = get_temp_alert_config(addressing, | ||
| 1059 | emif->plat_data->custom_configs, device_info->cs1_used, | ||
| 1060 | device_info->io_width, get_emif_bus_width(emif)); | ||
| 1061 | writel(temp_alert_cfg, base + EMIF_TEMPERATURE_ALERT_CONFIG); | ||
| 1062 | |||
| 1063 | /* | ||
| 1064 | * Program external PHY control registers that are not frequency | ||
| 1065 | * dependent | ||
| 1066 | */ | ||
| 1067 | if (emif->plat_data->phy_type != EMIF_PHY_TYPE_INTELLIPHY) | ||
| 1068 | return; | ||
| 1069 | writel(EMIF_EXT_PHY_CTRL_1_VAL, base + EMIF_EXT_PHY_CTRL_1_SHDW); | ||
| 1070 | writel(EMIF_EXT_PHY_CTRL_5_VAL, base + EMIF_EXT_PHY_CTRL_5_SHDW); | ||
| 1071 | writel(EMIF_EXT_PHY_CTRL_6_VAL, base + EMIF_EXT_PHY_CTRL_6_SHDW); | ||
| 1072 | writel(EMIF_EXT_PHY_CTRL_7_VAL, base + EMIF_EXT_PHY_CTRL_7_SHDW); | ||
| 1073 | writel(EMIF_EXT_PHY_CTRL_8_VAL, base + EMIF_EXT_PHY_CTRL_8_SHDW); | ||
| 1074 | writel(EMIF_EXT_PHY_CTRL_9_VAL, base + EMIF_EXT_PHY_CTRL_9_SHDW); | ||
| 1075 | writel(EMIF_EXT_PHY_CTRL_10_VAL, base + EMIF_EXT_PHY_CTRL_10_SHDW); | ||
| 1076 | writel(EMIF_EXT_PHY_CTRL_11_VAL, base + EMIF_EXT_PHY_CTRL_11_SHDW); | ||
| 1077 | writel(EMIF_EXT_PHY_CTRL_12_VAL, base + EMIF_EXT_PHY_CTRL_12_SHDW); | ||
| 1078 | writel(EMIF_EXT_PHY_CTRL_13_VAL, base + EMIF_EXT_PHY_CTRL_13_SHDW); | ||
| 1079 | writel(EMIF_EXT_PHY_CTRL_14_VAL, base + EMIF_EXT_PHY_CTRL_14_SHDW); | ||
| 1080 | writel(EMIF_EXT_PHY_CTRL_15_VAL, base + EMIF_EXT_PHY_CTRL_15_SHDW); | ||
| 1081 | writel(EMIF_EXT_PHY_CTRL_16_VAL, base + EMIF_EXT_PHY_CTRL_16_SHDW); | ||
| 1082 | writel(EMIF_EXT_PHY_CTRL_17_VAL, base + EMIF_EXT_PHY_CTRL_17_SHDW); | ||
| 1083 | writel(EMIF_EXT_PHY_CTRL_18_VAL, base + EMIF_EXT_PHY_CTRL_18_SHDW); | ||
| 1084 | writel(EMIF_EXT_PHY_CTRL_19_VAL, base + EMIF_EXT_PHY_CTRL_19_SHDW); | ||
| 1085 | writel(EMIF_EXT_PHY_CTRL_20_VAL, base + EMIF_EXT_PHY_CTRL_20_SHDW); | ||
| 1086 | writel(EMIF_EXT_PHY_CTRL_21_VAL, base + EMIF_EXT_PHY_CTRL_21_SHDW); | ||
| 1087 | writel(EMIF_EXT_PHY_CTRL_22_VAL, base + EMIF_EXT_PHY_CTRL_22_SHDW); | ||
| 1088 | writel(EMIF_EXT_PHY_CTRL_23_VAL, base + EMIF_EXT_PHY_CTRL_23_SHDW); | ||
| 1089 | writel(EMIF_EXT_PHY_CTRL_24_VAL, base + EMIF_EXT_PHY_CTRL_24_SHDW); | ||
| 1090 | } | ||
| 1091 | |||
| 1092 | static void get_default_timings(struct emif_data *emif) | ||
| 1093 | { | ||
| 1094 | struct emif_platform_data *pd = emif->plat_data; | ||
| 1095 | |||
| 1096 | pd->timings = lpddr2_jedec_timings; | ||
| 1097 | pd->timings_arr_size = ARRAY_SIZE(lpddr2_jedec_timings); | ||
| 1098 | |||
| 1099 | dev_warn(emif->dev, "%s: using default timings\n", __func__); | ||
| 1100 | } | ||
| 1101 | |||
| 1102 | static int is_dev_data_valid(u32 type, u32 density, u32 io_width, u32 phy_type, | ||
| 1103 | u32 ip_rev, struct device *dev) | ||
| 1104 | { | ||
| 1105 | int valid; | ||
| 1106 | |||
| 1107 | valid = (type == DDR_TYPE_LPDDR2_S4 || | ||
| 1108 | type == DDR_TYPE_LPDDR2_S2) | ||
| 1109 | && (density >= DDR_DENSITY_64Mb | ||
| 1110 | && density <= DDR_DENSITY_8Gb) | ||
| 1111 | && (io_width >= DDR_IO_WIDTH_8 | ||
| 1112 | && io_width <= DDR_IO_WIDTH_32); | ||
| 1113 | |||
| 1114 | /* Combinations of EMIF and PHY revisions that we support today */ | ||
| 1115 | switch (ip_rev) { | ||
| 1116 | case EMIF_4D: | ||
| 1117 | valid = valid && (phy_type == EMIF_PHY_TYPE_ATTILAPHY); | ||
| 1118 | break; | ||
| 1119 | case EMIF_4D5: | ||
| 1120 | valid = valid && (phy_type == EMIF_PHY_TYPE_INTELLIPHY); | ||
| 1121 | break; | ||
| 1122 | default: | ||
| 1123 | valid = 0; | ||
| 1124 | } | ||
| 1125 | |||
| 1126 | if (!valid) | ||
| 1127 | dev_err(dev, "%s: invalid DDR details\n", __func__); | ||
| 1128 | return valid; | ||
| 1129 | } | ||
| 1130 | |||
| 1131 | static int is_custom_config_valid(struct emif_custom_configs *cust_cfgs, | ||
| 1132 | struct device *dev) | ||
| 1133 | { | ||
| 1134 | int valid = 1; | ||
| 1135 | |||
| 1136 | if ((cust_cfgs->mask & EMIF_CUSTOM_CONFIG_LPMODE) && | ||
| 1137 | (cust_cfgs->lpmode != EMIF_LP_MODE_DISABLE)) | ||
| 1138 | valid = cust_cfgs->lpmode_freq_threshold && | ||
| 1139 | cust_cfgs->lpmode_timeout_performance && | ||
| 1140 | cust_cfgs->lpmode_timeout_power; | ||
| 1141 | |||
| 1142 | if (cust_cfgs->mask & EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL) | ||
| 1143 | valid = valid && cust_cfgs->temp_alert_poll_interval_ms; | ||
| 1144 | |||
| 1145 | if (!valid) | ||
| 1146 | dev_warn(dev, "%s: invalid custom configs\n", __func__); | ||
| 1147 | |||
| 1148 | return valid; | ||
| 1149 | } | ||
| 1150 | |||
| 1151 | static struct emif_data *__init_or_module get_device_details( | ||
| 1152 | struct platform_device *pdev) | ||
| 1153 | { | ||
| 1154 | u32 size; | ||
| 1155 | struct emif_data *emif = NULL; | ||
| 1156 | struct ddr_device_info *dev_info; | ||
| 1157 | struct emif_custom_configs *cust_cfgs; | ||
| 1158 | struct emif_platform_data *pd; | ||
| 1159 | struct device *dev; | ||
| 1160 | void *temp; | ||
| 1161 | |||
| 1162 | pd = pdev->dev.platform_data; | ||
| 1163 | dev = &pdev->dev; | ||
| 1164 | |||
| 1165 | if (!(pd && pd->device_info && is_dev_data_valid(pd->device_info->type, | ||
| 1166 | pd->device_info->density, pd->device_info->io_width, | ||
| 1167 | pd->phy_type, pd->ip_rev, dev))) { | ||
| 1168 | dev_err(dev, "%s: invalid device data\n", __func__); | ||
| 1169 | goto error; | ||
| 1170 | } | ||
| 1171 | |||
| 1172 | emif = devm_kzalloc(dev, sizeof(*emif), GFP_KERNEL); | ||
| 1173 | temp = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); | ||
| 1174 | dev_info = devm_kzalloc(dev, sizeof(*dev_info), GFP_KERNEL); | ||
| 1175 | |||
| 1176 | if (!emif || !pd || !dev_info) { | ||
| 1177 | dev_err(dev, "%s:%d: allocation error\n", __func__, __LINE__); | ||
| 1178 | goto error; | ||
| 1179 | } | ||
| 1180 | |||
| 1181 | memcpy(temp, pd, sizeof(*pd)); | ||
| 1182 | pd = temp; | ||
| 1183 | memcpy(dev_info, pd->device_info, sizeof(*dev_info)); | ||
| 1184 | |||
| 1185 | pd->device_info = dev_info; | ||
| 1186 | emif->plat_data = pd; | ||
| 1187 | emif->dev = dev; | ||
| 1188 | emif->temperature_level = SDRAM_TEMP_NOMINAL; | ||
| 1189 | |||
| 1190 | /* | ||
| 1191 | * For EMIF instances other than EMIF1 see if the devices connected | ||
| 1192 | * are exactly same as on EMIF1(which is typically the case). If so, | ||
| 1193 | * mark it as a duplicate of EMIF1 and skip copying timings data. | ||
| 1194 | * This will save some memory and some computation later. | ||
| 1195 | */ | ||
| 1196 | emif->duplicate = emif1 && (memcmp(dev_info, | ||
| 1197 | emif1->plat_data->device_info, | ||
| 1198 | sizeof(struct ddr_device_info)) == 0); | ||
| 1199 | |||
| 1200 | if (emif->duplicate) { | ||
| 1201 | pd->timings = NULL; | ||
| 1202 | pd->min_tck = NULL; | ||
| 1203 | goto out; | ||
| 1204 | } else if (emif1) { | ||
| 1205 | dev_warn(emif->dev, "%s: Non-symmetric DDR geometry\n", | ||
| 1206 | __func__); | ||
| 1207 | } | ||
| 1208 | |||
| 1209 | /* | ||
| 1210 | * Copy custom configs - ignore allocation error, if any, as | ||
| 1211 | * custom_configs is not very critical | ||
| 1212 | */ | ||
| 1213 | cust_cfgs = pd->custom_configs; | ||
| 1214 | if (cust_cfgs && is_custom_config_valid(cust_cfgs, dev)) { | ||
| 1215 | temp = devm_kzalloc(dev, sizeof(*cust_cfgs), GFP_KERNEL); | ||
| 1216 | if (temp) | ||
| 1217 | memcpy(temp, cust_cfgs, sizeof(*cust_cfgs)); | ||
| 1218 | else | ||
| 1219 | dev_warn(dev, "%s:%d: allocation error\n", __func__, | ||
| 1220 | __LINE__); | ||
| 1221 | pd->custom_configs = temp; | ||
| 1222 | } | ||
| 1223 | |||
| 1224 | /* | ||
| 1225 | * Copy timings and min-tck values from platform data. If it is not | ||
| 1226 | * available or if memory allocation fails, use JEDEC defaults | ||
| 1227 | */ | ||
| 1228 | size = sizeof(struct lpddr2_timings) * pd->timings_arr_size; | ||
| 1229 | if (pd->timings) { | ||
| 1230 | temp = devm_kzalloc(dev, size, GFP_KERNEL); | ||
| 1231 | if (temp) { | ||
| 1232 | memcpy(temp, pd->timings, sizeof(*pd->timings)); | ||
| 1233 | pd->timings = temp; | ||
| 1234 | } else { | ||
| 1235 | dev_warn(dev, "%s:%d: allocation error\n", __func__, | ||
| 1236 | __LINE__); | ||
| 1237 | get_default_timings(emif); | ||
| 1238 | } | ||
| 1239 | } else { | ||
| 1240 | get_default_timings(emif); | ||
| 1241 | } | ||
| 1242 | |||
| 1243 | if (pd->min_tck) { | ||
| 1244 | temp = devm_kzalloc(dev, sizeof(*pd->min_tck), GFP_KERNEL); | ||
| 1245 | if (temp) { | ||
| 1246 | memcpy(temp, pd->min_tck, sizeof(*pd->min_tck)); | ||
| 1247 | pd->min_tck = temp; | ||
| 1248 | } else { | ||
| 1249 | dev_warn(dev, "%s:%d: allocation error\n", __func__, | ||
| 1250 | __LINE__); | ||
| 1251 | pd->min_tck = &lpddr2_jedec_min_tck; | ||
| 1252 | } | ||
| 1253 | } else { | ||
| 1254 | pd->min_tck = &lpddr2_jedec_min_tck; | ||
| 1255 | } | ||
| 1256 | |||
| 1257 | out: | ||
| 1258 | return emif; | ||
| 1259 | |||
| 1260 | error: | ||
| 1261 | return NULL; | ||
| 1262 | } | ||
| 1263 | |||
| 1264 | static int __init_or_module emif_probe(struct platform_device *pdev) | ||
| 1265 | { | ||
| 1266 | struct emif_data *emif; | ||
| 1267 | struct resource *res; | ||
| 1268 | int irq; | ||
| 1269 | |||
| 1270 | emif = get_device_details(pdev); | ||
| 1271 | if (!emif) { | ||
| 1272 | pr_err("%s: error getting device data\n", __func__); | ||
| 1273 | goto error; | ||
| 1274 | } | ||
| 1275 | |||
| 1276 | list_add(&emif->node, &device_list); | ||
| 1277 | emif->addressing = get_addressing_table(emif->plat_data->device_info); | ||
| 1278 | |||
| 1279 | /* Save pointers to each other in emif and device structures */ | ||
| 1280 | emif->dev = &pdev->dev; | ||
| 1281 | platform_set_drvdata(pdev, emif); | ||
| 1282 | |||
| 1283 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 1284 | if (!res) { | ||
| 1285 | dev_err(emif->dev, "%s: error getting memory resource\n", | ||
| 1286 | __func__); | ||
| 1287 | goto error; | ||
| 1288 | } | ||
| 1289 | |||
| 1290 | emif->base = devm_request_and_ioremap(emif->dev, res); | ||
| 1291 | if (!emif->base) { | ||
| 1292 | dev_err(emif->dev, "%s: devm_request_and_ioremap() failed\n", | ||
| 1293 | __func__); | ||
| 1294 | goto error; | ||
| 1295 | } | ||
| 1296 | |||
| 1297 | irq = platform_get_irq(pdev, 0); | ||
| 1298 | if (irq < 0) { | ||
| 1299 | dev_err(emif->dev, "%s: error getting IRQ resource - %d\n", | ||
| 1300 | __func__, irq); | ||
| 1301 | goto error; | ||
| 1302 | } | ||
| 1303 | |||
| 1304 | emif_onetime_settings(emif); | ||
| 1305 | emif_debugfs_init(emif); | ||
| 1306 | disable_and_clear_all_interrupts(emif); | ||
| 1307 | setup_interrupts(emif, irq); | ||
| 1308 | |||
| 1309 | /* One-time actions taken on probing the first device */ | ||
| 1310 | if (!emif1) { | ||
| 1311 | emif1 = emif; | ||
| 1312 | spin_lock_init(&emif_lock); | ||
| 1313 | |||
| 1314 | /* | ||
| 1315 | * TODO: register notifiers for frequency and voltage | ||
| 1316 | * change here once the respective frameworks are | ||
| 1317 | * available | ||
| 1318 | */ | ||
| 1319 | } | ||
| 1320 | |||
| 1321 | dev_info(&pdev->dev, "%s: device configured with addr = %p and IRQ%d\n", | ||
| 1322 | __func__, emif->base, irq); | ||
| 1323 | |||
| 1324 | return 0; | ||
| 1325 | error: | ||
| 1326 | return -ENODEV; | ||
| 1327 | } | ||
| 1328 | |||
| 1329 | static int __exit emif_remove(struct platform_device *pdev) | ||
| 1330 | { | ||
| 1331 | struct emif_data *emif = platform_get_drvdata(pdev); | ||
| 1332 | |||
| 1333 | emif_debugfs_exit(emif); | ||
| 1334 | |||
| 1335 | return 0; | ||
| 1336 | } | ||
| 1337 | |||
| 1338 | static void emif_shutdown(struct platform_device *pdev) | ||
| 1339 | { | ||
| 1340 | struct emif_data *emif = platform_get_drvdata(pdev); | ||
| 1341 | |||
| 1342 | disable_and_clear_all_interrupts(emif); | ||
| 1343 | } | ||
| 1344 | |||
| 1345 | static int get_emif_reg_values(struct emif_data *emif, u32 freq, | ||
| 1346 | struct emif_regs *regs) | ||
| 1347 | { | ||
| 1348 | u32 cs1_used, ip_rev, phy_type; | ||
| 1349 | u32 cl, type; | ||
| 1350 | const struct lpddr2_timings *timings; | ||
| 1351 | const struct lpddr2_min_tck *min_tck; | ||
| 1352 | const struct ddr_device_info *device_info; | ||
| 1353 | const struct lpddr2_addressing *addressing; | ||
| 1354 | struct emif_data *emif_for_calc; | ||
| 1355 | struct device *dev; | ||
| 1356 | const struct emif_custom_configs *custom_configs; | ||
| 1357 | |||
| 1358 | dev = emif->dev; | ||
| 1359 | /* | ||
| 1360 | * If the devices on this EMIF instance is duplicate of EMIF1, | ||
| 1361 | * use EMIF1 details for the calculation | ||
| 1362 | */ | ||
| 1363 | emif_for_calc = emif->duplicate ? emif1 : emif; | ||
| 1364 | timings = get_timings_table(emif_for_calc, freq); | ||
| 1365 | addressing = emif_for_calc->addressing; | ||
| 1366 | if (!timings || !addressing) { | ||
| 1367 | dev_err(dev, "%s: not enough data available for %dHz", | ||
| 1368 | __func__, freq); | ||
| 1369 | return -1; | ||
| 1370 | } | ||
| 1371 | |||
| 1372 | device_info = emif_for_calc->plat_data->device_info; | ||
| 1373 | type = device_info->type; | ||
| 1374 | cs1_used = device_info->cs1_used; | ||
| 1375 | ip_rev = emif_for_calc->plat_data->ip_rev; | ||
| 1376 | phy_type = emif_for_calc->plat_data->phy_type; | ||
| 1377 | |||
| 1378 | min_tck = emif_for_calc->plat_data->min_tck; | ||
| 1379 | custom_configs = emif_for_calc->plat_data->custom_configs; | ||
| 1380 | |||
| 1381 | set_ddr_clk_period(freq); | ||
| 1382 | |||
| 1383 | regs->ref_ctrl_shdw = get_sdram_ref_ctrl_shdw(freq, addressing); | ||
| 1384 | regs->sdram_tim1_shdw = get_sdram_tim_1_shdw(timings, min_tck, | ||
| 1385 | addressing); | ||
| 1386 | regs->sdram_tim2_shdw = get_sdram_tim_2_shdw(timings, min_tck, | ||
| 1387 | addressing, type); | ||
| 1388 | regs->sdram_tim3_shdw = get_sdram_tim_3_shdw(timings, min_tck, | ||
| 1389 | addressing, type, ip_rev, EMIF_NORMAL_TIMINGS); | ||
| 1390 | |||
| 1391 | cl = get_cl(emif); | ||
| 1392 | |||
| 1393 | if (phy_type == EMIF_PHY_TYPE_ATTILAPHY && ip_rev == EMIF_4D) { | ||
| 1394 | regs->phy_ctrl_1_shdw = get_ddr_phy_ctrl_1_attilaphy_4d( | ||
| 1395 | timings, freq, cl); | ||
| 1396 | } else if (phy_type == EMIF_PHY_TYPE_INTELLIPHY && ip_rev == EMIF_4D5) { | ||
| 1397 | regs->phy_ctrl_1_shdw = get_phy_ctrl_1_intelliphy_4d5(freq, cl); | ||
| 1398 | regs->ext_phy_ctrl_2_shdw = get_ext_phy_ctrl_2_intelliphy_4d5(); | ||
| 1399 | regs->ext_phy_ctrl_3_shdw = get_ext_phy_ctrl_3_intelliphy_4d5(); | ||
| 1400 | regs->ext_phy_ctrl_4_shdw = get_ext_phy_ctrl_4_intelliphy_4d5(); | ||
| 1401 | } else { | ||
| 1402 | return -1; | ||
| 1403 | } | ||
| 1404 | |||
| 1405 | /* Only timeout values in pwr_mgmt_ctrl_shdw register */ | ||
| 1406 | regs->pwr_mgmt_ctrl_shdw = | ||
| 1407 | get_pwr_mgmt_ctrl(freq, emif_for_calc, ip_rev) & | ||
| 1408 | (CS_TIM_MASK | SR_TIM_MASK | PD_TIM_MASK); | ||
| 1409 | |||
| 1410 | if (ip_rev & EMIF_4D) { | ||
| 1411 | regs->read_idle_ctrl_shdw_normal = | ||
| 1412 | get_read_idle_ctrl_shdw(DDR_VOLTAGE_STABLE); | ||
| 1413 | |||
| 1414 | regs->read_idle_ctrl_shdw_volt_ramp = | ||
| 1415 | get_read_idle_ctrl_shdw(DDR_VOLTAGE_RAMPING); | ||
| 1416 | } else if (ip_rev & EMIF_4D5) { | ||
| 1417 | regs->dll_calib_ctrl_shdw_normal = | ||
| 1418 | get_dll_calib_ctrl_shdw(DDR_VOLTAGE_STABLE); | ||
| 1419 | |||
| 1420 | regs->dll_calib_ctrl_shdw_volt_ramp = | ||
| 1421 | get_dll_calib_ctrl_shdw(DDR_VOLTAGE_RAMPING); | ||
| 1422 | } | ||
| 1423 | |||
| 1424 | if (type == DDR_TYPE_LPDDR2_S2 || type == DDR_TYPE_LPDDR2_S4) { | ||
| 1425 | regs->ref_ctrl_shdw_derated = get_sdram_ref_ctrl_shdw(freq / 4, | ||
| 1426 | addressing); | ||
| 1427 | |||
| 1428 | regs->sdram_tim1_shdw_derated = | ||
| 1429 | get_sdram_tim_1_shdw_derated(timings, min_tck, | ||
| 1430 | addressing); | ||
| 1431 | |||
| 1432 | regs->sdram_tim3_shdw_derated = get_sdram_tim_3_shdw(timings, | ||
| 1433 | min_tck, addressing, type, ip_rev, | ||
| 1434 | EMIF_DERATED_TIMINGS); | ||
| 1435 | } | ||
| 1436 | |||
| 1437 | regs->freq = freq; | ||
| 1438 | |||
| 1439 | return 0; | ||
| 1440 | } | ||
| 1441 | |||
| 1442 | /* | ||
| 1443 | * get_regs() - gets the cached emif_regs structure for a given EMIF instance | ||
| 1444 | * given frequency(freq): | ||
| 1445 | * | ||
| 1446 | * As an optimisation, every EMIF instance other than EMIF1 shares the | ||
| 1447 | * register cache with EMIF1 if the devices connected on this instance | ||
| 1448 | * are same as that on EMIF1(indicated by the duplicate flag) | ||
| 1449 | * | ||
| 1450 | * If we do not have an entry corresponding to the frequency given, we | ||
| 1451 | * allocate a new entry and calculate the values | ||
| 1452 | * | ||
| 1453 | * Upon finding the right reg dump, save it in curr_regs. It can be | ||
| 1454 | * directly used for thermal de-rating and voltage ramping changes. | ||
| 1455 | */ | ||
| 1456 | static struct emif_regs *get_regs(struct emif_data *emif, u32 freq) | ||
| 1457 | { | ||
| 1458 | int i; | ||
| 1459 | struct emif_regs **regs_cache; | ||
| 1460 | struct emif_regs *regs = NULL; | ||
| 1461 | struct device *dev; | ||
| 1462 | |||
| 1463 | dev = emif->dev; | ||
| 1464 | if (emif->curr_regs && emif->curr_regs->freq == freq) { | ||
| 1465 | dev_dbg(dev, "%s: using curr_regs - %u Hz", __func__, freq); | ||
| 1466 | return emif->curr_regs; | ||
| 1467 | } | ||
| 1468 | |||
| 1469 | if (emif->duplicate) | ||
| 1470 | regs_cache = emif1->regs_cache; | ||
| 1471 | else | ||
| 1472 | regs_cache = emif->regs_cache; | ||
| 1473 | |||
| 1474 | for (i = 0; i < EMIF_MAX_NUM_FREQUENCIES && regs_cache[i]; i++) { | ||
| 1475 | if (regs_cache[i]->freq == freq) { | ||
| 1476 | regs = regs_cache[i]; | ||
| 1477 | dev_dbg(dev, | ||
| 1478 | "%s: reg dump found in reg cache for %u Hz\n", | ||
| 1479 | __func__, freq); | ||
| 1480 | break; | ||
| 1481 | } | ||
| 1482 | } | ||
| 1483 | |||
| 1484 | /* | ||
| 1485 | * If we don't have an entry for this frequency in the cache create one | ||
| 1486 | * and calculate the values | ||
| 1487 | */ | ||
| 1488 | if (!regs) { | ||
| 1489 | regs = devm_kzalloc(emif->dev, sizeof(*regs), GFP_ATOMIC); | ||
| 1490 | if (!regs) | ||
| 1491 | return NULL; | ||
| 1492 | |||
| 1493 | if (get_emif_reg_values(emif, freq, regs)) { | ||
| 1494 | devm_kfree(emif->dev, regs); | ||
| 1495 | return NULL; | ||
| 1496 | } | ||
| 1497 | |||
| 1498 | /* | ||
| 1499 | * Now look for an un-used entry in the cache and save the | ||
| 1500 | * newly created struct. If there are no free entries | ||
| 1501 | * over-write the last entry | ||
| 1502 | */ | ||
| 1503 | for (i = 0; i < EMIF_MAX_NUM_FREQUENCIES && regs_cache[i]; i++) | ||
| 1504 | ; | ||
| 1505 | |||
| 1506 | if (i >= EMIF_MAX_NUM_FREQUENCIES) { | ||
| 1507 | dev_warn(dev, "%s: regs_cache full - reusing a slot!!\n", | ||
| 1508 | __func__); | ||
| 1509 | i = EMIF_MAX_NUM_FREQUENCIES - 1; | ||
| 1510 | devm_kfree(emif->dev, regs_cache[i]); | ||
| 1511 | } | ||
| 1512 | regs_cache[i] = regs; | ||
| 1513 | } | ||
| 1514 | |||
| 1515 | return regs; | ||
| 1516 | } | ||
| 1517 | |||
| 1518 | static void do_volt_notify_handling(struct emif_data *emif, u32 volt_state) | ||
| 1519 | { | ||
| 1520 | dev_dbg(emif->dev, "%s: voltage notification : %d", __func__, | ||
| 1521 | volt_state); | ||
| 1522 | |||
| 1523 | if (!emif->curr_regs) { | ||
| 1524 | dev_err(emif->dev, | ||
| 1525 | "%s: volt-notify before registers are ready: %d\n", | ||
| 1526 | __func__, volt_state); | ||
| 1527 | return; | ||
| 1528 | } | ||
| 1529 | |||
| 1530 | setup_volt_sensitive_regs(emif, emif->curr_regs, volt_state); | ||
| 1531 | } | ||
| 1532 | |||
| 1533 | /* | ||
| 1534 | * TODO: voltage notify handling should be hooked up to | ||
| 1535 | * regulator framework as soon as the necessary support | ||
| 1536 | * is available in mainline kernel. This function is un-used | ||
| 1537 | * right now. | ||
| 1538 | */ | ||
| 1539 | static void __attribute__((unused)) volt_notify_handling(u32 volt_state) | ||
| 1540 | { | ||
| 1541 | struct emif_data *emif; | ||
| 1542 | |||
| 1543 | spin_lock_irqsave(&emif_lock, irq_state); | ||
| 1544 | |||
| 1545 | list_for_each_entry(emif, &device_list, node) | ||
| 1546 | do_volt_notify_handling(emif, volt_state); | ||
| 1547 | do_freq_update(); | ||
| 1548 | |||
| 1549 | spin_unlock_irqrestore(&emif_lock, irq_state); | ||
| 1550 | } | ||
| 1551 | |||
| 1552 | static void do_freq_pre_notify_handling(struct emif_data *emif, u32 new_freq) | ||
| 1553 | { | ||
| 1554 | struct emif_regs *regs; | ||
| 1555 | |||
| 1556 | regs = get_regs(emif, new_freq); | ||
| 1557 | if (!regs) | ||
| 1558 | return; | ||
| 1559 | |||
| 1560 | emif->curr_regs = regs; | ||
| 1561 | |||
| 1562 | /* | ||
| 1563 | * Update the shadow registers: | ||
| 1564 | * Temperature and voltage-ramp sensitive settings are also configured | ||
| 1565 | * in terms of DDR cycles. So, we need to update them too when there | ||
| 1566 | * is a freq change | ||
| 1567 | */ | ||
| 1568 | dev_dbg(emif->dev, "%s: setting up shadow registers for %uHz", | ||
| 1569 | __func__, new_freq); | ||
| 1570 | setup_registers(emif, regs); | ||
| 1571 | setup_temperature_sensitive_regs(emif, regs); | ||
| 1572 | setup_volt_sensitive_regs(emif, regs, DDR_VOLTAGE_STABLE); | ||
| 1573 | |||
| 1574 | /* | ||
| 1575 | * Part of workaround for errata i728. See do_freq_update() | ||
| 1576 | * for more details | ||
| 1577 | */ | ||
| 1578 | if (emif->lpmode == EMIF_LP_MODE_SELF_REFRESH) | ||
| 1579 | set_lpmode(emif, EMIF_LP_MODE_DISABLE); | ||
| 1580 | } | ||
| 1581 | |||
| 1582 | /* | ||
| 1583 | * TODO: frequency notify handling should be hooked up to | ||
| 1584 | * clock framework as soon as the necessary support is | ||
| 1585 | * available in mainline kernel. This function is un-used | ||
| 1586 | * right now. | ||
| 1587 | */ | ||
| 1588 | static void __attribute__((unused)) freq_pre_notify_handling(u32 new_freq) | ||
| 1589 | { | ||
| 1590 | struct emif_data *emif; | ||
| 1591 | |||
| 1592 | /* | ||
| 1593 | * NOTE: we are taking the spin-lock here and releases it | ||
| 1594 | * only in post-notifier. This doesn't look good and | ||
| 1595 | * Sparse complains about it, but this seems to be | ||
| 1596 | * un-avoidable. We need to lock a sequence of events | ||
| 1597 | * that is split between EMIF and clock framework. | ||
| 1598 | * | ||
| 1599 | * 1. EMIF driver updates EMIF timings in shadow registers in the | ||
| 1600 | * frequency pre-notify callback from clock framework | ||
| 1601 | * 2. clock framework sets up the registers for the new frequency | ||
| 1602 | * 3. clock framework initiates a hw-sequence that updates | ||
| 1603 | * the frequency EMIF timings synchronously. | ||
| 1604 | * | ||
| 1605 | * All these 3 steps should be performed as an atomic operation | ||
| 1606 | * vis-a-vis similar sequence in the EMIF interrupt handler | ||
| 1607 | * for temperature events. Otherwise, there could be race | ||
| 1608 | * conditions that could result in incorrect EMIF timings for | ||
| 1609 | * a given frequency | ||
| 1610 | */ | ||
| 1611 | spin_lock_irqsave(&emif_lock, irq_state); | ||
| 1612 | |||
| 1613 | list_for_each_entry(emif, &device_list, node) | ||
| 1614 | do_freq_pre_notify_handling(emif, new_freq); | ||
| 1615 | } | ||
| 1616 | |||
| 1617 | static void do_freq_post_notify_handling(struct emif_data *emif) | ||
| 1618 | { | ||
| 1619 | /* | ||
| 1620 | * Part of workaround for errata i728. See do_freq_update() | ||
| 1621 | * for more details | ||
| 1622 | */ | ||
| 1623 | if (emif->lpmode == EMIF_LP_MODE_SELF_REFRESH) | ||
| 1624 | set_lpmode(emif, EMIF_LP_MODE_SELF_REFRESH); | ||
| 1625 | } | ||
| 1626 | |||
| 1627 | /* | ||
| 1628 | * TODO: frequency notify handling should be hooked up to | ||
| 1629 | * clock framework as soon as the necessary support is | ||
| 1630 | * available in mainline kernel. This function is un-used | ||
| 1631 | * right now. | ||
| 1632 | */ | ||
| 1633 | static void __attribute__((unused)) freq_post_notify_handling(void) | ||
| 1634 | { | ||
| 1635 | struct emif_data *emif; | ||
| 1636 | |||
| 1637 | list_for_each_entry(emif, &device_list, node) | ||
| 1638 | do_freq_post_notify_handling(emif); | ||
| 1639 | |||
| 1640 | /* | ||
| 1641 | * Lock is done in pre-notify handler. See freq_pre_notify_handling() | ||
| 1642 | * for more details | ||
| 1643 | */ | ||
| 1644 | spin_unlock_irqrestore(&emif_lock, irq_state); | ||
| 1645 | } | ||
| 1646 | |||
| 1647 | static struct platform_driver emif_driver = { | ||
| 1648 | .remove = __exit_p(emif_remove), | ||
| 1649 | .shutdown = emif_shutdown, | ||
| 1650 | .driver = { | ||
| 1651 | .name = "emif", | ||
| 1652 | }, | ||
| 1653 | }; | ||
| 1654 | |||
| 1655 | static int __init_or_module emif_register(void) | ||
| 1656 | { | ||
| 1657 | return platform_driver_probe(&emif_driver, emif_probe); | ||
| 1658 | } | ||
| 1659 | |||
| 1660 | static void __exit emif_unregister(void) | ||
| 1661 | { | ||
| 1662 | platform_driver_unregister(&emif_driver); | ||
| 1663 | } | ||
| 1664 | |||
| 1665 | module_init(emif_register); | ||
| 1666 | module_exit(emif_unregister); | ||
| 1667 | MODULE_DESCRIPTION("TI EMIF SDRAM Controller Driver"); | ||
| 1668 | MODULE_LICENSE("GPL"); | ||
| 1669 | MODULE_ALIAS("platform:emif"); | ||
| 1670 | MODULE_AUTHOR("Texas Instruments Inc"); | ||
diff --git a/drivers/memory/emif.h b/drivers/memory/emif.h new file mode 100644 index 000000000000..bfe08bae961a --- /dev/null +++ b/drivers/memory/emif.h | |||
| @@ -0,0 +1,589 @@ | |||
| 1 | /* | ||
| 2 | * Defines for the EMIF driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Texas Instruments, Inc. | ||
| 5 | * | ||
| 6 | * Benoit Cousson (b-cousson@ti.com) | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | #ifndef __EMIF_H | ||
| 13 | #define __EMIF_H | ||
| 14 | |||
| 15 | /* | ||
| 16 | * Maximum number of different frequencies supported by EMIF driver | ||
| 17 | * Determines the number of entries in the pointer array for register | ||
| 18 | * cache | ||
| 19 | */ | ||
| 20 | #define EMIF_MAX_NUM_FREQUENCIES 6 | ||
| 21 | |||
| 22 | /* State of the core voltage */ | ||
| 23 | #define DDR_VOLTAGE_STABLE 0 | ||
| 24 | #define DDR_VOLTAGE_RAMPING 1 | ||
| 25 | |||
| 26 | /* Defines for timing De-rating */ | ||
| 27 | #define EMIF_NORMAL_TIMINGS 0 | ||
| 28 | #define EMIF_DERATED_TIMINGS 1 | ||
| 29 | |||
| 30 | /* Length of the forced read idle period in terms of cycles */ | ||
| 31 | #define EMIF_READ_IDLE_LEN_VAL 5 | ||
| 32 | |||
| 33 | /* | ||
| 34 | * forced read idle interval to be used when voltage | ||
| 35 | * is changed as part of DVFS/DPS - 1ms | ||
| 36 | */ | ||
| 37 | #define READ_IDLE_INTERVAL_DVFS (1*1000000) | ||
| 38 | |||
| 39 | /* | ||
| 40 | * Forced read idle interval to be used when voltage is stable | ||
| 41 | * 50us - or maximum value will do | ||
| 42 | */ | ||
| 43 | #define READ_IDLE_INTERVAL_NORMAL (50*1000000) | ||
| 44 | |||
| 45 | /* DLL calibration interval when voltage is NOT stable - 1us */ | ||
| 46 | #define DLL_CALIB_INTERVAL_DVFS (1*1000000) | ||
| 47 | |||
| 48 | #define DLL_CALIB_ACK_WAIT_VAL 5 | ||
| 49 | |||
| 50 | /* Interval between ZQCS commands - hw team recommended value */ | ||
| 51 | #define EMIF_ZQCS_INTERVAL_US (50*1000) | ||
| 52 | /* Enable ZQ Calibration on exiting Self-refresh */ | ||
| 53 | #define ZQ_SFEXITEN_ENABLE 1 | ||
| 54 | /* | ||
| 55 | * ZQ Calibration simultaneously on both chip-selects: | ||
| 56 | * Needs one calibration resistor per CS | ||
| 57 | */ | ||
| 58 | #define ZQ_DUALCALEN_DISABLE 0 | ||
| 59 | #define ZQ_DUALCALEN_ENABLE 1 | ||
| 60 | |||
| 61 | #define T_ZQCS_DEFAULT_NS 90 | ||
| 62 | #define T_ZQCL_DEFAULT_NS 360 | ||
| 63 | #define T_ZQINIT_DEFAULT_NS 1000 | ||
| 64 | |||
| 65 | /* DPD_EN */ | ||
| 66 | #define DPD_DISABLE 0 | ||
| 67 | #define DPD_ENABLE 1 | ||
| 68 | |||
| 69 | /* | ||
| 70 | * Default values for the low-power entry to be used if not provided by user. | ||
| 71 | * OMAP4/5 has a hw bug(i735) due to which this value can not be less than 512 | ||
| 72 | * Timeout values are in DDR clock 'cycles' and frequency threshold in Hz | ||
| 73 | */ | ||
| 74 | #define EMIF_LP_MODE_TIMEOUT_PERFORMANCE 2048 | ||
| 75 | #define EMIF_LP_MODE_TIMEOUT_POWER 512 | ||
| 76 | #define EMIF_LP_MODE_FREQ_THRESHOLD 400000000 | ||
| 77 | |||
| 78 | /* DDR_PHY_CTRL_1 values for EMIF4D - ATTILA PHY combination */ | ||
| 79 | #define EMIF_DDR_PHY_CTRL_1_BASE_VAL_ATTILAPHY 0x049FF000 | ||
| 80 | #define EMIF_DLL_SLAVE_DLY_CTRL_400_MHZ_ATTILAPHY 0x41 | ||
| 81 | #define EMIF_DLL_SLAVE_DLY_CTRL_200_MHZ_ATTILAPHY 0x80 | ||
| 82 | #define EMIF_DLL_SLAVE_DLY_CTRL_100_MHZ_AND_LESS_ATTILAPHY 0xFF | ||
| 83 | |||
| 84 | /* DDR_PHY_CTRL_1 values for EMIF4D5 INTELLIPHY combination */ | ||
| 85 | #define EMIF_DDR_PHY_CTRL_1_BASE_VAL_INTELLIPHY 0x0E084200 | ||
| 86 | #define EMIF_PHY_TOTAL_READ_LATENCY_INTELLIPHY_PS 10000 | ||
| 87 | |||
| 88 | /* TEMP_ALERT_CONFIG - corresponding to temp gradient 5 C/s */ | ||
| 89 | #define TEMP_ALERT_POLL_INTERVAL_DEFAULT_MS 360 | ||
| 90 | |||
| 91 | #define EMIF_T_CSTA 3 | ||
| 92 | #define EMIF_T_PDLL_UL 128 | ||
| 93 | |||
| 94 | /* External PHY control registers magic values */ | ||
| 95 | #define EMIF_EXT_PHY_CTRL_1_VAL 0x04020080 | ||
| 96 | #define EMIF_EXT_PHY_CTRL_5_VAL 0x04010040 | ||
| 97 | #define EMIF_EXT_PHY_CTRL_6_VAL 0x01004010 | ||
| 98 | #define EMIF_EXT_PHY_CTRL_7_VAL 0x00001004 | ||
| 99 | #define EMIF_EXT_PHY_CTRL_8_VAL 0x04010040 | ||
| 100 | #define EMIF_EXT_PHY_CTRL_9_VAL 0x01004010 | ||
| 101 | #define EMIF_EXT_PHY_CTRL_10_VAL 0x00001004 | ||
| 102 | #define EMIF_EXT_PHY_CTRL_11_VAL 0x00000000 | ||
| 103 | #define EMIF_EXT_PHY_CTRL_12_VAL 0x00000000 | ||
| 104 | #define EMIF_EXT_PHY_CTRL_13_VAL 0x00000000 | ||
| 105 | #define EMIF_EXT_PHY_CTRL_14_VAL 0x80080080 | ||
| 106 | #define EMIF_EXT_PHY_CTRL_15_VAL 0x00800800 | ||
| 107 | #define EMIF_EXT_PHY_CTRL_16_VAL 0x08102040 | ||
| 108 | #define EMIF_EXT_PHY_CTRL_17_VAL 0x00000001 | ||
| 109 | #define EMIF_EXT_PHY_CTRL_18_VAL 0x540A8150 | ||
| 110 | #define EMIF_EXT_PHY_CTRL_19_VAL 0xA81502A0 | ||
| 111 | #define EMIF_EXT_PHY_CTRL_20_VAL 0x002A0540 | ||
| 112 | #define EMIF_EXT_PHY_CTRL_21_VAL 0x00000000 | ||
| 113 | #define EMIF_EXT_PHY_CTRL_22_VAL 0x00000000 | ||
| 114 | #define EMIF_EXT_PHY_CTRL_23_VAL 0x00000000 | ||
| 115 | #define EMIF_EXT_PHY_CTRL_24_VAL 0x00000077 | ||
| 116 | |||
| 117 | #define EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS 1200 | ||
| 118 | |||
| 119 | /* Registers offset */ | ||
| 120 | #define EMIF_MODULE_ID_AND_REVISION 0x0000 | ||
| 121 | #define EMIF_STATUS 0x0004 | ||
| 122 | #define EMIF_SDRAM_CONFIG 0x0008 | ||
| 123 | #define EMIF_SDRAM_CONFIG_2 0x000c | ||
| 124 | #define EMIF_SDRAM_REFRESH_CONTROL 0x0010 | ||
| 125 | #define EMIF_SDRAM_REFRESH_CTRL_SHDW 0x0014 | ||
| 126 | #define EMIF_SDRAM_TIMING_1 0x0018 | ||
| 127 | #define EMIF_SDRAM_TIMING_1_SHDW 0x001c | ||
| 128 | #define EMIF_SDRAM_TIMING_2 0x0020 | ||
| 129 | #define EMIF_SDRAM_TIMING_2_SHDW 0x0024 | ||
| 130 | #define EMIF_SDRAM_TIMING_3 0x0028 | ||
| 131 | #define EMIF_SDRAM_TIMING_3_SHDW 0x002c | ||
| 132 | #define EMIF_LPDDR2_NVM_TIMING 0x0030 | ||
| 133 | #define EMIF_LPDDR2_NVM_TIMING_SHDW 0x0034 | ||
| 134 | #define EMIF_POWER_MANAGEMENT_CONTROL 0x0038 | ||
| 135 | #define EMIF_POWER_MANAGEMENT_CTRL_SHDW 0x003c | ||
| 136 | #define EMIF_LPDDR2_MODE_REG_DATA 0x0040 | ||
| 137 | #define EMIF_LPDDR2_MODE_REG_CONFIG 0x0050 | ||
| 138 | #define EMIF_OCP_CONFIG 0x0054 | ||
| 139 | #define EMIF_OCP_CONFIG_VALUE_1 0x0058 | ||
| 140 | #define EMIF_OCP_CONFIG_VALUE_2 0x005c | ||
| 141 | #define EMIF_IODFT_TEST_LOGIC_GLOBAL_CONTROL 0x0060 | ||
| 142 | #define EMIF_IODFT_TEST_LOGIC_CTRL_MISR_RESULT 0x0064 | ||
| 143 | #define EMIF_IODFT_TEST_LOGIC_ADDRESS_MISR_RESULT 0x0068 | ||
| 144 | #define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_1 0x006c | ||
| 145 | #define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_2 0x0070 | ||
| 146 | #define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_3 0x0074 | ||
| 147 | #define EMIF_PERFORMANCE_COUNTER_1 0x0080 | ||
| 148 | #define EMIF_PERFORMANCE_COUNTER_2 0x0084 | ||
| 149 | #define EMIF_PERFORMANCE_COUNTER_CONFIG 0x0088 | ||
| 150 | #define EMIF_PERFORMANCE_COUNTER_MASTER_REGION_SELECT 0x008c | ||
| 151 | #define EMIF_PERFORMANCE_COUNTER_TIME 0x0090 | ||
| 152 | #define EMIF_MISC_REG 0x0094 | ||
| 153 | #define EMIF_DLL_CALIB_CTRL 0x0098 | ||
| 154 | #define EMIF_DLL_CALIB_CTRL_SHDW 0x009c | ||
| 155 | #define EMIF_END_OF_INTERRUPT 0x00a0 | ||
| 156 | #define EMIF_SYSTEM_OCP_INTERRUPT_RAW_STATUS 0x00a4 | ||
| 157 | #define EMIF_LL_OCP_INTERRUPT_RAW_STATUS 0x00a8 | ||
| 158 | #define EMIF_SYSTEM_OCP_INTERRUPT_STATUS 0x00ac | ||
| 159 | #define EMIF_LL_OCP_INTERRUPT_STATUS 0x00b0 | ||
| 160 | #define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET 0x00b4 | ||
| 161 | #define EMIF_LL_OCP_INTERRUPT_ENABLE_SET 0x00b8 | ||
| 162 | #define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_CLEAR 0x00bc | ||
| 163 | #define EMIF_LL_OCP_INTERRUPT_ENABLE_CLEAR 0x00c0 | ||
| 164 | #define EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG 0x00c8 | ||
| 165 | #define EMIF_TEMPERATURE_ALERT_CONFIG 0x00cc | ||
| 166 | #define EMIF_OCP_ERROR_LOG 0x00d0 | ||
| 167 | #define EMIF_READ_WRITE_LEVELING_RAMP_WINDOW 0x00d4 | ||
| 168 | #define EMIF_READ_WRITE_LEVELING_RAMP_CONTROL 0x00d8 | ||
| 169 | #define EMIF_READ_WRITE_LEVELING_CONTROL 0x00dc | ||
| 170 | #define EMIF_DDR_PHY_CTRL_1 0x00e4 | ||
| 171 | #define EMIF_DDR_PHY_CTRL_1_SHDW 0x00e8 | ||
| 172 | #define EMIF_DDR_PHY_CTRL_2 0x00ec | ||
| 173 | #define EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING 0x0100 | ||
| 174 | #define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING 0x0104 | ||
| 175 | #define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING 0x0108 | ||
| 176 | #define EMIF_READ_WRITE_EXECUTION_THRESHOLD 0x0120 | ||
| 177 | #define EMIF_COS_CONFIG 0x0124 | ||
| 178 | #define EMIF_PHY_STATUS_1 0x0140 | ||
| 179 | #define EMIF_PHY_STATUS_2 0x0144 | ||
| 180 | #define EMIF_PHY_STATUS_3 0x0148 | ||
| 181 | #define EMIF_PHY_STATUS_4 0x014c | ||
| 182 | #define EMIF_PHY_STATUS_5 0x0150 | ||
| 183 | #define EMIF_PHY_STATUS_6 0x0154 | ||
| 184 | #define EMIF_PHY_STATUS_7 0x0158 | ||
| 185 | #define EMIF_PHY_STATUS_8 0x015c | ||
| 186 | #define EMIF_PHY_STATUS_9 0x0160 | ||
| 187 | #define EMIF_PHY_STATUS_10 0x0164 | ||
| 188 | #define EMIF_PHY_STATUS_11 0x0168 | ||
| 189 | #define EMIF_PHY_STATUS_12 0x016c | ||
| 190 | #define EMIF_PHY_STATUS_13 0x0170 | ||
| 191 | #define EMIF_PHY_STATUS_14 0x0174 | ||
| 192 | #define EMIF_PHY_STATUS_15 0x0178 | ||
| 193 | #define EMIF_PHY_STATUS_16 0x017c | ||
| 194 | #define EMIF_PHY_STATUS_17 0x0180 | ||
| 195 | #define EMIF_PHY_STATUS_18 0x0184 | ||
| 196 | #define EMIF_PHY_STATUS_19 0x0188 | ||
| 197 | #define EMIF_PHY_STATUS_20 0x018c | ||
| 198 | #define EMIF_PHY_STATUS_21 0x0190 | ||
| 199 | #define EMIF_EXT_PHY_CTRL_1 0x0200 | ||
| 200 | #define EMIF_EXT_PHY_CTRL_1_SHDW 0x0204 | ||
| 201 | #define EMIF_EXT_PHY_CTRL_2 0x0208 | ||
| 202 | #define EMIF_EXT_PHY_CTRL_2_SHDW 0x020c | ||
| 203 | #define EMIF_EXT_PHY_CTRL_3 0x0210 | ||
| 204 | #define EMIF_EXT_PHY_CTRL_3_SHDW 0x0214 | ||
| 205 | #define EMIF_EXT_PHY_CTRL_4 0x0218 | ||
| 206 | #define EMIF_EXT_PHY_CTRL_4_SHDW 0x021c | ||
| 207 | #define EMIF_EXT_PHY_CTRL_5 0x0220 | ||
| 208 | #define EMIF_EXT_PHY_CTRL_5_SHDW 0x0224 | ||
| 209 | #define EMIF_EXT_PHY_CTRL_6 0x0228 | ||
| 210 | #define EMIF_EXT_PHY_CTRL_6_SHDW 0x022c | ||
| 211 | #define EMIF_EXT_PHY_CTRL_7 0x0230 | ||
| 212 | #define EMIF_EXT_PHY_CTRL_7_SHDW 0x0234 | ||
| 213 | #define EMIF_EXT_PHY_CTRL_8 0x0238 | ||
| 214 | #define EMIF_EXT_PHY_CTRL_8_SHDW 0x023c | ||
| 215 | #define EMIF_EXT_PHY_CTRL_9 0x0240 | ||
| 216 | #define EMIF_EXT_PHY_CTRL_9_SHDW 0x0244 | ||
| 217 | #define EMIF_EXT_PHY_CTRL_10 0x0248 | ||
| 218 | #define EMIF_EXT_PHY_CTRL_10_SHDW 0x024c | ||
| 219 | #define EMIF_EXT_PHY_CTRL_11 0x0250 | ||
| 220 | #define EMIF_EXT_PHY_CTRL_11_SHDW 0x0254 | ||
| 221 | #define EMIF_EXT_PHY_CTRL_12 0x0258 | ||
| 222 | #define EMIF_EXT_PHY_CTRL_12_SHDW 0x025c | ||
| 223 | #define EMIF_EXT_PHY_CTRL_13 0x0260 | ||
| 224 | #define EMIF_EXT_PHY_CTRL_13_SHDW 0x0264 | ||
| 225 | #define EMIF_EXT_PHY_CTRL_14 0x0268 | ||
| 226 | #define EMIF_EXT_PHY_CTRL_14_SHDW 0x026c | ||
| 227 | #define EMIF_EXT_PHY_CTRL_15 0x0270 | ||
| 228 | #define EMIF_EXT_PHY_CTRL_15_SHDW 0x0274 | ||
| 229 | #define EMIF_EXT_PHY_CTRL_16 0x0278 | ||
| 230 | #define EMIF_EXT_PHY_CTRL_16_SHDW 0x027c | ||
| 231 | #define EMIF_EXT_PHY_CTRL_17 0x0280 | ||
| 232 | #define EMIF_EXT_PHY_CTRL_17_SHDW 0x0284 | ||
| 233 | #define EMIF_EXT_PHY_CTRL_18 0x0288 | ||
| 234 | #define EMIF_EXT_PHY_CTRL_18_SHDW 0x028c | ||
| 235 | #define EMIF_EXT_PHY_CTRL_19 0x0290 | ||
| 236 | #define EMIF_EXT_PHY_CTRL_19_SHDW 0x0294 | ||
| 237 | #define EMIF_EXT_PHY_CTRL_20 0x0298 | ||
| 238 | #define EMIF_EXT_PHY_CTRL_20_SHDW 0x029c | ||
| 239 | #define EMIF_EXT_PHY_CTRL_21 0x02a0 | ||
| 240 | #define EMIF_EXT_PHY_CTRL_21_SHDW 0x02a4 | ||
| 241 | #define EMIF_EXT_PHY_CTRL_22 0x02a8 | ||
| 242 | #define EMIF_EXT_PHY_CTRL_22_SHDW 0x02ac | ||
| 243 | #define EMIF_EXT_PHY_CTRL_23 0x02b0 | ||
| 244 | #define EMIF_EXT_PHY_CTRL_23_SHDW 0x02b4 | ||
| 245 | #define EMIF_EXT_PHY_CTRL_24 0x02b8 | ||
| 246 | #define EMIF_EXT_PHY_CTRL_24_SHDW 0x02bc | ||
| 247 | #define EMIF_EXT_PHY_CTRL_25 0x02c0 | ||
| 248 | #define EMIF_EXT_PHY_CTRL_25_SHDW 0x02c4 | ||
| 249 | #define EMIF_EXT_PHY_CTRL_26 0x02c8 | ||
| 250 | #define EMIF_EXT_PHY_CTRL_26_SHDW 0x02cc | ||
| 251 | #define EMIF_EXT_PHY_CTRL_27 0x02d0 | ||
| 252 | #define EMIF_EXT_PHY_CTRL_27_SHDW 0x02d4 | ||
| 253 | #define EMIF_EXT_PHY_CTRL_28 0x02d8 | ||
| 254 | #define EMIF_EXT_PHY_CTRL_28_SHDW 0x02dc | ||
| 255 | #define EMIF_EXT_PHY_CTRL_29 0x02e0 | ||
| 256 | #define EMIF_EXT_PHY_CTRL_29_SHDW 0x02e4 | ||
| 257 | #define EMIF_EXT_PHY_CTRL_30 0x02e8 | ||
| 258 | #define EMIF_EXT_PHY_CTRL_30_SHDW 0x02ec | ||
| 259 | |||
| 260 | /* Registers shifts and masks */ | ||
| 261 | |||
| 262 | /* EMIF_MODULE_ID_AND_REVISION */ | ||
| 263 | #define SCHEME_SHIFT 30 | ||
| 264 | #define SCHEME_MASK (0x3 << 30) | ||
| 265 | #define MODULE_ID_SHIFT 16 | ||
| 266 | #define MODULE_ID_MASK (0xfff << 16) | ||
| 267 | #define RTL_VERSION_SHIFT 11 | ||
| 268 | #define RTL_VERSION_MASK (0x1f << 11) | ||
| 269 | #define MAJOR_REVISION_SHIFT 8 | ||
| 270 | #define MAJOR_REVISION_MASK (0x7 << 8) | ||
| 271 | #define MINOR_REVISION_SHIFT 0 | ||
| 272 | #define MINOR_REVISION_MASK (0x3f << 0) | ||
| 273 | |||
| 274 | /* STATUS */ | ||
| 275 | #define BE_SHIFT 31 | ||
| 276 | #define BE_MASK (1 << 31) | ||
| 277 | #define DUAL_CLK_MODE_SHIFT 30 | ||
| 278 | #define DUAL_CLK_MODE_MASK (1 << 30) | ||
| 279 | #define FAST_INIT_SHIFT 29 | ||
| 280 | #define FAST_INIT_MASK (1 << 29) | ||
| 281 | #define RDLVLGATETO_SHIFT 6 | ||
| 282 | #define RDLVLGATETO_MASK (1 << 6) | ||
| 283 | #define RDLVLTO_SHIFT 5 | ||
| 284 | #define RDLVLTO_MASK (1 << 5) | ||
| 285 | #define WRLVLTO_SHIFT 4 | ||
| 286 | #define WRLVLTO_MASK (1 << 4) | ||
| 287 | #define PHY_DLL_READY_SHIFT 2 | ||
| 288 | #define PHY_DLL_READY_MASK (1 << 2) | ||
| 289 | |||
| 290 | /* SDRAM_CONFIG */ | ||
| 291 | #define SDRAM_TYPE_SHIFT 29 | ||
| 292 | #define SDRAM_TYPE_MASK (0x7 << 29) | ||
| 293 | #define IBANK_POS_SHIFT 27 | ||
| 294 | #define IBANK_POS_MASK (0x3 << 27) | ||
| 295 | #define DDR_TERM_SHIFT 24 | ||
| 296 | #define DDR_TERM_MASK (0x7 << 24) | ||
| 297 | #define DDR2_DDQS_SHIFT 23 | ||
| 298 | #define DDR2_DDQS_MASK (1 << 23) | ||
| 299 | #define DYN_ODT_SHIFT 21 | ||
| 300 | #define DYN_ODT_MASK (0x3 << 21) | ||
| 301 | #define DDR_DISABLE_DLL_SHIFT 20 | ||
| 302 | #define DDR_DISABLE_DLL_MASK (1 << 20) | ||
| 303 | #define SDRAM_DRIVE_SHIFT 18 | ||
| 304 | #define SDRAM_DRIVE_MASK (0x3 << 18) | ||
| 305 | #define CWL_SHIFT 16 | ||
| 306 | #define CWL_MASK (0x3 << 16) | ||
| 307 | #define NARROW_MODE_SHIFT 14 | ||
| 308 | #define NARROW_MODE_MASK (0x3 << 14) | ||
| 309 | #define CL_SHIFT 10 | ||
| 310 | #define CL_MASK (0xf << 10) | ||
| 311 | #define ROWSIZE_SHIFT 7 | ||
| 312 | #define ROWSIZE_MASK (0x7 << 7) | ||
| 313 | #define IBANK_SHIFT 4 | ||
| 314 | #define IBANK_MASK (0x7 << 4) | ||
| 315 | #define EBANK_SHIFT 3 | ||
| 316 | #define EBANK_MASK (1 << 3) | ||
| 317 | #define PAGESIZE_SHIFT 0 | ||
| 318 | #define PAGESIZE_MASK (0x7 << 0) | ||
| 319 | |||
| 320 | /* SDRAM_CONFIG_2 */ | ||
| 321 | #define CS1NVMEN_SHIFT 30 | ||
| 322 | #define CS1NVMEN_MASK (1 << 30) | ||
| 323 | #define EBANK_POS_SHIFT 27 | ||
| 324 | #define EBANK_POS_MASK (1 << 27) | ||
| 325 | #define RDBNUM_SHIFT 4 | ||
| 326 | #define RDBNUM_MASK (0x3 << 4) | ||
| 327 | #define RDBSIZE_SHIFT 0 | ||
| 328 | #define RDBSIZE_MASK (0x7 << 0) | ||
| 329 | |||
| 330 | /* SDRAM_REFRESH_CONTROL */ | ||
| 331 | #define INITREF_DIS_SHIFT 31 | ||
| 332 | #define INITREF_DIS_MASK (1 << 31) | ||
| 333 | #define SRT_SHIFT 29 | ||
| 334 | #define SRT_MASK (1 << 29) | ||
| 335 | #define ASR_SHIFT 28 | ||
| 336 | #define ASR_MASK (1 << 28) | ||
| 337 | #define PASR_SHIFT 24 | ||
| 338 | #define PASR_MASK (0x7 << 24) | ||
| 339 | #define REFRESH_RATE_SHIFT 0 | ||
| 340 | #define REFRESH_RATE_MASK (0xffff << 0) | ||
| 341 | |||
| 342 | /* SDRAM_TIMING_1 */ | ||
| 343 | #define T_RTW_SHIFT 29 | ||
| 344 | #define T_RTW_MASK (0x7 << 29) | ||
| 345 | #define T_RP_SHIFT 25 | ||
| 346 | #define T_RP_MASK (0xf << 25) | ||
| 347 | #define T_RCD_SHIFT 21 | ||
| 348 | #define T_RCD_MASK (0xf << 21) | ||
| 349 | #define T_WR_SHIFT 17 | ||
| 350 | #define T_WR_MASK (0xf << 17) | ||
| 351 | #define T_RAS_SHIFT 12 | ||
| 352 | #define T_RAS_MASK (0x1f << 12) | ||
| 353 | #define T_RC_SHIFT 6 | ||
| 354 | #define T_RC_MASK (0x3f << 6) | ||
| 355 | #define T_RRD_SHIFT 3 | ||
| 356 | #define T_RRD_MASK (0x7 << 3) | ||
| 357 | #define T_WTR_SHIFT 0 | ||
| 358 | #define T_WTR_MASK (0x7 << 0) | ||
| 359 | |||
| 360 | /* SDRAM_TIMING_2 */ | ||
| 361 | #define T_XP_SHIFT 28 | ||
| 362 | #define T_XP_MASK (0x7 << 28) | ||
| 363 | #define T_ODT_SHIFT 25 | ||
| 364 | #define T_ODT_MASK (0x7 << 25) | ||
| 365 | #define T_XSNR_SHIFT 16 | ||
| 366 | #define T_XSNR_MASK (0x1ff << 16) | ||
| 367 | #define T_XSRD_SHIFT 6 | ||
| 368 | #define T_XSRD_MASK (0x3ff << 6) | ||
| 369 | #define T_RTP_SHIFT 3 | ||
| 370 | #define T_RTP_MASK (0x7 << 3) | ||
| 371 | #define T_CKE_SHIFT 0 | ||
| 372 | #define T_CKE_MASK (0x7 << 0) | ||
| 373 | |||
| 374 | /* SDRAM_TIMING_3 */ | ||
| 375 | #define T_PDLL_UL_SHIFT 28 | ||
| 376 | #define T_PDLL_UL_MASK (0xf << 28) | ||
| 377 | #define T_CSTA_SHIFT 24 | ||
| 378 | #define T_CSTA_MASK (0xf << 24) | ||
| 379 | #define T_CKESR_SHIFT 21 | ||
| 380 | #define T_CKESR_MASK (0x7 << 21) | ||
| 381 | #define ZQ_ZQCS_SHIFT 15 | ||
| 382 | #define ZQ_ZQCS_MASK (0x3f << 15) | ||
| 383 | #define T_TDQSCKMAX_SHIFT 13 | ||
| 384 | #define T_TDQSCKMAX_MASK (0x3 << 13) | ||
| 385 | #define T_RFC_SHIFT 4 | ||
| 386 | #define T_RFC_MASK (0x1ff << 4) | ||
| 387 | #define T_RAS_MAX_SHIFT 0 | ||
| 388 | #define T_RAS_MAX_MASK (0xf << 0) | ||
| 389 | |||
| 390 | /* POWER_MANAGEMENT_CONTROL */ | ||
| 391 | #define PD_TIM_SHIFT 12 | ||
| 392 | #define PD_TIM_MASK (0xf << 12) | ||
| 393 | #define DPD_EN_SHIFT 11 | ||
| 394 | #define DPD_EN_MASK (1 << 11) | ||
| 395 | #define LP_MODE_SHIFT 8 | ||
| 396 | #define LP_MODE_MASK (0x7 << 8) | ||
| 397 | #define SR_TIM_SHIFT 4 | ||
| 398 | #define SR_TIM_MASK (0xf << 4) | ||
| 399 | #define CS_TIM_SHIFT 0 | ||
| 400 | #define CS_TIM_MASK (0xf << 0) | ||
| 401 | |||
| 402 | /* LPDDR2_MODE_REG_DATA */ | ||
| 403 | #define VALUE_0_SHIFT 0 | ||
| 404 | #define VALUE_0_MASK (0x7f << 0) | ||
| 405 | |||
| 406 | /* LPDDR2_MODE_REG_CONFIG */ | ||
| 407 | #define CS_SHIFT 31 | ||
| 408 | #define CS_MASK (1 << 31) | ||
| 409 | #define REFRESH_EN_SHIFT 30 | ||
| 410 | #define REFRESH_EN_MASK (1 << 30) | ||
| 411 | #define ADDRESS_SHIFT 0 | ||
| 412 | #define ADDRESS_MASK (0xff << 0) | ||
| 413 | |||
| 414 | /* OCP_CONFIG */ | ||
| 415 | #define SYS_THRESH_MAX_SHIFT 24 | ||
| 416 | #define SYS_THRESH_MAX_MASK (0xf << 24) | ||
| 417 | #define MPU_THRESH_MAX_SHIFT 20 | ||
| 418 | #define MPU_THRESH_MAX_MASK (0xf << 20) | ||
| 419 | #define LL_THRESH_MAX_SHIFT 16 | ||
| 420 | #define LL_THRESH_MAX_MASK (0xf << 16) | ||
| 421 | |||
| 422 | /* PERFORMANCE_COUNTER_1 */ | ||
| 423 | #define COUNTER1_SHIFT 0 | ||
| 424 | #define COUNTER1_MASK (0xffffffff << 0) | ||
| 425 | |||
| 426 | /* PERFORMANCE_COUNTER_2 */ | ||
| 427 | #define COUNTER2_SHIFT 0 | ||
| 428 | #define COUNTER2_MASK (0xffffffff << 0) | ||
| 429 | |||
| 430 | /* PERFORMANCE_COUNTER_CONFIG */ | ||
| 431 | #define CNTR2_MCONNID_EN_SHIFT 31 | ||
| 432 | #define CNTR2_MCONNID_EN_MASK (1 << 31) | ||
| 433 | #define CNTR2_REGION_EN_SHIFT 30 | ||
| 434 | #define CNTR2_REGION_EN_MASK (1 << 30) | ||
| 435 | #define CNTR2_CFG_SHIFT 16 | ||
| 436 | #define CNTR2_CFG_MASK (0xf << 16) | ||
| 437 | #define CNTR1_MCONNID_EN_SHIFT 15 | ||
| 438 | #define CNTR1_MCONNID_EN_MASK (1 << 15) | ||
| 439 | #define CNTR1_REGION_EN_SHIFT 14 | ||
| 440 | #define CNTR1_REGION_EN_MASK (1 << 14) | ||
| 441 | #define CNTR1_CFG_SHIFT 0 | ||
| 442 | #define CNTR1_CFG_MASK (0xf << 0) | ||
| 443 | |||
| 444 | /* PERFORMANCE_COUNTER_MASTER_REGION_SELECT */ | ||
| 445 | #define MCONNID2_SHIFT 24 | ||
| 446 | #define MCONNID2_MASK (0xff << 24) | ||
| 447 | #define REGION_SEL2_SHIFT 16 | ||
| 448 | #define REGION_SEL2_MASK (0x3 << 16) | ||
| 449 | #define MCONNID1_SHIFT 8 | ||
| 450 | #define MCONNID1_MASK (0xff << 8) | ||
| 451 | #define REGION_SEL1_SHIFT 0 | ||
| 452 | #define REGION_SEL1_MASK (0x3 << 0) | ||
| 453 | |||
| 454 | /* PERFORMANCE_COUNTER_TIME */ | ||
| 455 | #define TOTAL_TIME_SHIFT 0 | ||
| 456 | #define TOTAL_TIME_MASK (0xffffffff << 0) | ||
| 457 | |||
| 458 | /* DLL_CALIB_CTRL */ | ||
| 459 | #define ACK_WAIT_SHIFT 16 | ||
| 460 | #define ACK_WAIT_MASK (0xf << 16) | ||
| 461 | #define DLL_CALIB_INTERVAL_SHIFT 0 | ||
| 462 | #define DLL_CALIB_INTERVAL_MASK (0x1ff << 0) | ||
| 463 | |||
| 464 | /* END_OF_INTERRUPT */ | ||
| 465 | #define EOI_SHIFT 0 | ||
| 466 | #define EOI_MASK (1 << 0) | ||
| 467 | |||
| 468 | /* SYSTEM_OCP_INTERRUPT_RAW_STATUS */ | ||
| 469 | #define DNV_SYS_SHIFT 2 | ||
| 470 | #define DNV_SYS_MASK (1 << 2) | ||
| 471 | #define TA_SYS_SHIFT 1 | ||
| 472 | #define TA_SYS_MASK (1 << 1) | ||
| 473 | #define ERR_SYS_SHIFT 0 | ||
| 474 | #define ERR_SYS_MASK (1 << 0) | ||
| 475 | |||
| 476 | /* LOW_LATENCY_OCP_INTERRUPT_RAW_STATUS */ | ||
| 477 | #define DNV_LL_SHIFT 2 | ||
| 478 | #define DNV_LL_MASK (1 << 2) | ||
| 479 | #define TA_LL_SHIFT 1 | ||
| 480 | #define TA_LL_MASK (1 << 1) | ||
| 481 | #define ERR_LL_SHIFT 0 | ||
| 482 | #define ERR_LL_MASK (1 << 0) | ||
| 483 | |||
| 484 | /* SYSTEM_OCP_INTERRUPT_ENABLE_SET */ | ||
| 485 | #define EN_DNV_SYS_SHIFT 2 | ||
| 486 | #define EN_DNV_SYS_MASK (1 << 2) | ||
| 487 | #define EN_TA_SYS_SHIFT 1 | ||
| 488 | #define EN_TA_SYS_MASK (1 << 1) | ||
| 489 | #define EN_ERR_SYS_SHIFT 0 | ||
| 490 | #define EN_ERR_SYS_MASK (1 << 0) | ||
| 491 | |||
| 492 | /* LOW_LATENCY_OCP_INTERRUPT_ENABLE_SET */ | ||
| 493 | #define EN_DNV_LL_SHIFT 2 | ||
| 494 | #define EN_DNV_LL_MASK (1 << 2) | ||
| 495 | #define EN_TA_LL_SHIFT 1 | ||
| 496 | #define EN_TA_LL_MASK (1 << 1) | ||
| 497 | #define EN_ERR_LL_SHIFT 0 | ||
| 498 | #define EN_ERR_LL_MASK (1 << 0) | ||
| 499 | |||
| 500 | /* SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG */ | ||
| 501 | #define ZQ_CS1EN_SHIFT 31 | ||
| 502 | #define ZQ_CS1EN_MASK (1 << 31) | ||
| 503 | #define ZQ_CS0EN_SHIFT 30 | ||
| 504 | #define ZQ_CS0EN_MASK (1 << 30) | ||
| 505 | #define ZQ_DUALCALEN_SHIFT 29 | ||
| 506 | #define ZQ_DUALCALEN_MASK (1 << 29) | ||
| 507 | #define ZQ_SFEXITEN_SHIFT 28 | ||
| 508 | #define ZQ_SFEXITEN_MASK (1 << 28) | ||
| 509 | #define ZQ_ZQINIT_MULT_SHIFT 18 | ||
| 510 | #define ZQ_ZQINIT_MULT_MASK (0x3 << 18) | ||
| 511 | #define ZQ_ZQCL_MULT_SHIFT 16 | ||
| 512 | #define ZQ_ZQCL_MULT_MASK (0x3 << 16) | ||
| 513 | #define ZQ_REFINTERVAL_SHIFT 0 | ||
| 514 | #define ZQ_REFINTERVAL_MASK (0xffff << 0) | ||
| 515 | |||
| 516 | /* TEMPERATURE_ALERT_CONFIG */ | ||
| 517 | #define TA_CS1EN_SHIFT 31 | ||
| 518 | #define TA_CS1EN_MASK (1 << 31) | ||
| 519 | #define TA_CS0EN_SHIFT 30 | ||
| 520 | #define TA_CS0EN_MASK (1 << 30) | ||
| 521 | #define TA_SFEXITEN_SHIFT 28 | ||
| 522 | #define TA_SFEXITEN_MASK (1 << 28) | ||
| 523 | #define TA_DEVWDT_SHIFT 26 | ||
| 524 | #define TA_DEVWDT_MASK (0x3 << 26) | ||
| 525 | #define TA_DEVCNT_SHIFT 24 | ||
| 526 | #define TA_DEVCNT_MASK (0x3 << 24) | ||
| 527 | #define TA_REFINTERVAL_SHIFT 0 | ||
| 528 | #define TA_REFINTERVAL_MASK (0x3fffff << 0) | ||
| 529 | |||
| 530 | /* OCP_ERROR_LOG */ | ||
| 531 | #define MADDRSPACE_SHIFT 14 | ||
| 532 | #define MADDRSPACE_MASK (0x3 << 14) | ||
| 533 | #define MBURSTSEQ_SHIFT 11 | ||
| 534 | #define MBURSTSEQ_MASK (0x7 << 11) | ||
| 535 | #define MCMD_SHIFT 8 | ||
| 536 | #define MCMD_MASK (0x7 << 8) | ||
| 537 | #define MCONNID_SHIFT 0 | ||
| 538 | #define MCONNID_MASK (0xff << 0) | ||
| 539 | |||
| 540 | /* DDR_PHY_CTRL_1 - EMIF4D */ | ||
| 541 | #define DLL_SLAVE_DLY_CTRL_SHIFT_4D 4 | ||
| 542 | #define DLL_SLAVE_DLY_CTRL_MASK_4D (0xFF << 4) | ||
| 543 | #define READ_LATENCY_SHIFT_4D 0 | ||
| 544 | #define READ_LATENCY_MASK_4D (0xf << 0) | ||
| 545 | |||
| 546 | /* DDR_PHY_CTRL_1 - EMIF4D5 */ | ||
| 547 | #define DLL_HALF_DELAY_SHIFT_4D5 21 | ||
| 548 | #define DLL_HALF_DELAY_MASK_4D5 (1 << 21) | ||
| 549 | #define READ_LATENCY_SHIFT_4D5 0 | ||
| 550 | #define READ_LATENCY_MASK_4D5 (0x1f << 0) | ||
| 551 | |||
| 552 | /* DDR_PHY_CTRL_1_SHDW */ | ||
| 553 | #define DDR_PHY_CTRL_1_SHDW_SHIFT 5 | ||
| 554 | #define DDR_PHY_CTRL_1_SHDW_MASK (0x7ffffff << 5) | ||
| 555 | #define READ_LATENCY_SHDW_SHIFT 0 | ||
| 556 | #define READ_LATENCY_SHDW_MASK (0x1f << 0) | ||
| 557 | |||
| 558 | #ifndef __ASSEMBLY__ | ||
| 559 | /* | ||
| 560 | * Structure containing shadow of important registers in EMIF | ||
| 561 | * The calculation function fills in this structure to be later used for | ||
| 562 | * initialisation and DVFS | ||
| 563 | */ | ||
| 564 | struct emif_regs { | ||
| 565 | u32 freq; | ||
| 566 | u32 ref_ctrl_shdw; | ||
| 567 | u32 ref_ctrl_shdw_derated; | ||
| 568 | u32 sdram_tim1_shdw; | ||
| 569 | u32 sdram_tim1_shdw_derated; | ||
| 570 | u32 sdram_tim2_shdw; | ||
| 571 | u32 sdram_tim3_shdw; | ||
| 572 | u32 sdram_tim3_shdw_derated; | ||
| 573 | u32 pwr_mgmt_ctrl_shdw; | ||
| 574 | union { | ||
| 575 | u32 read_idle_ctrl_shdw_normal; | ||
| 576 | u32 dll_calib_ctrl_shdw_normal; | ||
| 577 | }; | ||
| 578 | union { | ||
| 579 | u32 read_idle_ctrl_shdw_volt_ramp; | ||
| 580 | u32 dll_calib_ctrl_shdw_volt_ramp; | ||
| 581 | }; | ||
| 582 | |||
| 583 | u32 phy_ctrl_1_shdw; | ||
| 584 | u32 ext_phy_ctrl_2_shdw; | ||
| 585 | u32 ext_phy_ctrl_3_shdw; | ||
| 586 | u32 ext_phy_ctrl_4_shdw; | ||
| 587 | }; | ||
| 588 | #endif /* __ASSEMBLY__ */ | ||
| 589 | #endif /* __EMIF_H */ | ||
diff --git a/drivers/memory/tegra20-mc.c b/drivers/memory/tegra20-mc.c new file mode 100644 index 000000000000..3ed49c1c2b91 --- /dev/null +++ b/drivers/memory/tegra20-mc.c | |||
| @@ -0,0 +1,257 @@ | |||
| 1 | /* | ||
| 2 | * Tegra20 Memory Controller | ||
| 3 | * | ||
| 4 | * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms and conditions of the GNU General Public License, | ||
| 8 | * version 2, as published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 13 | * more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License along with | ||
| 16 | * this program; if not, write to the Free Software Foundation, Inc., | ||
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/kernel.h> | ||
| 21 | #include <linux/module.h> | ||
| 22 | #include <linux/ratelimit.h> | ||
| 23 | #include <linux/platform_device.h> | ||
| 24 | #include <linux/interrupt.h> | ||
| 25 | #include <linux/io.h> | ||
| 26 | |||
| 27 | #define DRV_NAME "tegra20-mc" | ||
| 28 | |||
| 29 | #define MC_INTSTATUS 0x0 | ||
| 30 | #define MC_INTMASK 0x4 | ||
| 31 | |||
| 32 | #define MC_INT_ERR_SHIFT 6 | ||
| 33 | #define MC_INT_ERR_MASK (0x1f << MC_INT_ERR_SHIFT) | ||
| 34 | #define MC_INT_DECERR_EMEM BIT(MC_INT_ERR_SHIFT) | ||
| 35 | #define MC_INT_INVALID_GART_PAGE BIT(MC_INT_ERR_SHIFT + 1) | ||
| 36 | #define MC_INT_SECURITY_VIOLATION BIT(MC_INT_ERR_SHIFT + 2) | ||
| 37 | #define MC_INT_ARBITRATION_EMEM BIT(MC_INT_ERR_SHIFT + 3) | ||
| 38 | |||
| 39 | #define MC_GART_ERROR_REQ 0x30 | ||
| 40 | #define MC_DECERR_EMEM_OTHERS_STATUS 0x58 | ||
| 41 | #define MC_SECURITY_VIOLATION_STATUS 0x74 | ||
| 42 | |||
| 43 | #define SECURITY_VIOLATION_TYPE BIT(30) /* 0=TRUSTZONE, 1=CARVEOUT */ | ||
| 44 | |||
| 45 | #define MC_CLIENT_ID_MASK 0x3f | ||
| 46 | |||
| 47 | #define NUM_MC_REG_BANKS 2 | ||
| 48 | |||
| 49 | struct tegra20_mc { | ||
| 50 | void __iomem *regs[NUM_MC_REG_BANKS]; | ||
| 51 | struct device *dev; | ||
| 52 | }; | ||
| 53 | |||
| 54 | static inline u32 mc_readl(struct tegra20_mc *mc, u32 offs) | ||
| 55 | { | ||
| 56 | u32 val = 0; | ||
| 57 | |||
| 58 | if (offs < 0x24) | ||
| 59 | val = readl(mc->regs[0] + offs); | ||
| 60 | if (offs < 0x400) | ||
| 61 | val = readl(mc->regs[1] + offs - 0x3c); | ||
| 62 | |||
| 63 | return val; | ||
| 64 | } | ||
| 65 | |||
| 66 | static inline void mc_writel(struct tegra20_mc *mc, u32 val, u32 offs) | ||
| 67 | { | ||
| 68 | if (offs < 0x24) { | ||
| 69 | writel(val, mc->regs[0] + offs); | ||
| 70 | return; | ||
| 71 | } | ||
| 72 | if (offs < 0x400) { | ||
| 73 | writel(val, mc->regs[1] + offs - 0x3c); | ||
| 74 | return; | ||
| 75 | } | ||
| 76 | } | ||
| 77 | |||
| 78 | static const char * const tegra20_mc_client[] = { | ||
| 79 | "cbr_display0a", | ||
| 80 | "cbr_display0ab", | ||
| 81 | "cbr_display0b", | ||
| 82 | "cbr_display0bb", | ||
| 83 | "cbr_display0c", | ||
| 84 | "cbr_display0cb", | ||
| 85 | "cbr_display1b", | ||
| 86 | "cbr_display1bb", | ||
| 87 | "cbr_eppup", | ||
| 88 | "cbr_g2pr", | ||
| 89 | "cbr_g2sr", | ||
| 90 | "cbr_mpeunifbr", | ||
| 91 | "cbr_viruv", | ||
| 92 | "csr_avpcarm7r", | ||
| 93 | "csr_displayhc", | ||
| 94 | "csr_displayhcb", | ||
| 95 | "csr_fdcdrd", | ||
| 96 | "csr_g2dr", | ||
| 97 | "csr_host1xdmar", | ||
| 98 | "csr_host1xr", | ||
| 99 | "csr_idxsrd", | ||
| 100 | "csr_mpcorer", | ||
| 101 | "csr_mpe_ipred", | ||
| 102 | "csr_mpeamemrd", | ||
| 103 | "csr_mpecsrd", | ||
| 104 | "csr_ppcsahbdmar", | ||
| 105 | "csr_ppcsahbslvr", | ||
| 106 | "csr_texsrd", | ||
| 107 | "csr_vdebsevr", | ||
| 108 | "csr_vdember", | ||
| 109 | "csr_vdemcer", | ||
| 110 | "csr_vdetper", | ||
| 111 | "cbw_eppu", | ||
| 112 | "cbw_eppv", | ||
| 113 | "cbw_eppy", | ||
| 114 | "cbw_mpeunifbw", | ||
| 115 | "cbw_viwsb", | ||
| 116 | "cbw_viwu", | ||
| 117 | "cbw_viwv", | ||
| 118 | "cbw_viwy", | ||
| 119 | "ccw_g2dw", | ||
| 120 | "csw_avpcarm7w", | ||
| 121 | "csw_fdcdwr", | ||
| 122 | "csw_host1xw", | ||
| 123 | "csw_ispw", | ||
| 124 | "csw_mpcorew", | ||
| 125 | "csw_mpecswr", | ||
| 126 | "csw_ppcsahbdmaw", | ||
| 127 | "csw_ppcsahbslvw", | ||
| 128 | "csw_vdebsevw", | ||
| 129 | "csw_vdembew", | ||
| 130 | "csw_vdetpmw", | ||
| 131 | }; | ||
| 132 | |||
| 133 | static void tegra20_mc_decode(struct tegra20_mc *mc, int n) | ||
| 134 | { | ||
| 135 | u32 addr, req; | ||
| 136 | const char *client = "Unknown"; | ||
| 137 | int idx, cid; | ||
| 138 | const struct reg_info { | ||
| 139 | u32 offset; | ||
| 140 | u32 write_bit; /* 0=READ, 1=WRITE */ | ||
| 141 | int cid_shift; | ||
| 142 | char *message; | ||
| 143 | } reg[] = { | ||
| 144 | { | ||
| 145 | .offset = MC_DECERR_EMEM_OTHERS_STATUS, | ||
| 146 | .write_bit = 31, | ||
| 147 | .message = "MC_DECERR", | ||
| 148 | }, | ||
| 149 | { | ||
| 150 | .offset = MC_GART_ERROR_REQ, | ||
| 151 | .cid_shift = 1, | ||
| 152 | .message = "MC_GART_ERR", | ||
| 153 | |||
| 154 | }, | ||
| 155 | { | ||
| 156 | .offset = MC_SECURITY_VIOLATION_STATUS, | ||
| 157 | .write_bit = 31, | ||
| 158 | .message = "MC_SECURITY_ERR", | ||
| 159 | }, | ||
| 160 | }; | ||
| 161 | |||
| 162 | idx = n - MC_INT_ERR_SHIFT; | ||
| 163 | if ((idx < 0) || (idx >= ARRAY_SIZE(reg))) { | ||
| 164 | dev_err_ratelimited(mc->dev, "Unknown interrupt status %08lx\n", | ||
| 165 | BIT(n)); | ||
| 166 | return; | ||
| 167 | } | ||
| 168 | |||
| 169 | req = mc_readl(mc, reg[idx].offset); | ||
| 170 | cid = (req >> reg[idx].cid_shift) & MC_CLIENT_ID_MASK; | ||
| 171 | if (cid < ARRAY_SIZE(tegra20_mc_client)) | ||
| 172 | client = tegra20_mc_client[cid]; | ||
| 173 | |||
| 174 | addr = mc_readl(mc, reg[idx].offset + sizeof(u32)); | ||
| 175 | |||
| 176 | dev_err_ratelimited(mc->dev, "%s (0x%08x): 0x%08x %s (%s %s)\n", | ||
| 177 | reg[idx].message, req, addr, client, | ||
| 178 | (req & BIT(reg[idx].write_bit)) ? "write" : "read", | ||
| 179 | (reg[idx].offset == MC_SECURITY_VIOLATION_STATUS) ? | ||
| 180 | ((req & SECURITY_VIOLATION_TYPE) ? | ||
| 181 | "carveout" : "trustzone") : ""); | ||
| 182 | } | ||
| 183 | |||
| 184 | static const struct of_device_id tegra20_mc_of_match[] __devinitconst = { | ||
| 185 | { .compatible = "nvidia,tegra20-mc", }, | ||
| 186 | {}, | ||
| 187 | }; | ||
| 188 | |||
| 189 | static irqreturn_t tegra20_mc_isr(int irq, void *data) | ||
| 190 | { | ||
| 191 | u32 stat, mask, bit; | ||
| 192 | struct tegra20_mc *mc = data; | ||
| 193 | |||
| 194 | stat = mc_readl(mc, MC_INTSTATUS); | ||
| 195 | mask = mc_readl(mc, MC_INTMASK); | ||
| 196 | mask &= stat; | ||
| 197 | if (!mask) | ||
| 198 | return IRQ_NONE; | ||
| 199 | while ((bit = ffs(mask)) != 0) | ||
| 200 | tegra20_mc_decode(mc, bit - 1); | ||
| 201 | mc_writel(mc, stat, MC_INTSTATUS); | ||
| 202 | return IRQ_HANDLED; | ||
| 203 | } | ||
| 204 | |||
| 205 | static int __devinit tegra20_mc_probe(struct platform_device *pdev) | ||
| 206 | { | ||
| 207 | struct resource *irq; | ||
| 208 | struct tegra20_mc *mc; | ||
| 209 | int i, err; | ||
| 210 | u32 intmask; | ||
| 211 | |||
| 212 | mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL); | ||
| 213 | if (!mc) | ||
| 214 | return -ENOMEM; | ||
| 215 | mc->dev = &pdev->dev; | ||
| 216 | |||
| 217 | for (i = 0; i < ARRAY_SIZE(mc->regs); i++) { | ||
| 218 | struct resource *res; | ||
| 219 | |||
| 220 | res = platform_get_resource(pdev, IORESOURCE_MEM, i); | ||
| 221 | if (!res) | ||
| 222 | return -ENODEV; | ||
| 223 | mc->regs[i] = devm_request_and_ioremap(&pdev->dev, res); | ||
| 224 | if (!mc->regs[i]) | ||
| 225 | return -EBUSY; | ||
| 226 | } | ||
| 227 | |||
| 228 | irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
| 229 | if (!irq) | ||
| 230 | return -ENODEV; | ||
| 231 | err = devm_request_irq(&pdev->dev, irq->start, tegra20_mc_isr, | ||
| 232 | IRQF_SHARED, dev_name(&pdev->dev), mc); | ||
| 233 | if (err) | ||
| 234 | return -ENODEV; | ||
| 235 | |||
| 236 | platform_set_drvdata(pdev, mc); | ||
| 237 | |||
| 238 | intmask = MC_INT_INVALID_GART_PAGE | | ||
| 239 | MC_INT_DECERR_EMEM | MC_INT_SECURITY_VIOLATION; | ||
| 240 | mc_writel(mc, intmask, MC_INTMASK); | ||
| 241 | return 0; | ||
| 242 | } | ||
| 243 | |||
| 244 | static struct platform_driver tegra20_mc_driver = { | ||
| 245 | .probe = tegra20_mc_probe, | ||
| 246 | .driver = { | ||
| 247 | .name = DRV_NAME, | ||
| 248 | .owner = THIS_MODULE, | ||
| 249 | .of_match_table = tegra20_mc_of_match, | ||
| 250 | }, | ||
| 251 | }; | ||
| 252 | module_platform_driver(tegra20_mc_driver); | ||
| 253 | |||
| 254 | MODULE_AUTHOR("Hiroshi DOYU <hdoyu@nvidia.com>"); | ||
| 255 | MODULE_DESCRIPTION("Tegra20 MC driver"); | ||
| 256 | MODULE_LICENSE("GPL v2"); | ||
| 257 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/drivers/memory/tegra30-mc.c b/drivers/memory/tegra30-mc.c new file mode 100644 index 000000000000..e56ff04eb5cc --- /dev/null +++ b/drivers/memory/tegra30-mc.c | |||
| @@ -0,0 +1,382 @@ | |||
| 1 | /* | ||
| 2 | * Tegra30 Memory Controller | ||
| 3 | * | ||
| 4 | * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms and conditions of the GNU General Public License, | ||
| 8 | * version 2, as published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 13 | * more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License along with | ||
| 16 | * this program; if not, write to the Free Software Foundation, Inc., | ||
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/kernel.h> | ||
| 21 | #include <linux/module.h> | ||
| 22 | #include <linux/ratelimit.h> | ||
| 23 | #include <linux/platform_device.h> | ||
| 24 | #include <linux/interrupt.h> | ||
| 25 | #include <linux/io.h> | ||
| 26 | |||
| 27 | #define DRV_NAME "tegra30-mc" | ||
| 28 | |||
| 29 | #define MC_INTSTATUS 0x0 | ||
| 30 | #define MC_INTMASK 0x4 | ||
| 31 | |||
| 32 | #define MC_INT_ERR_SHIFT 6 | ||
| 33 | #define MC_INT_ERR_MASK (0x1f << MC_INT_ERR_SHIFT) | ||
| 34 | #define MC_INT_DECERR_EMEM BIT(MC_INT_ERR_SHIFT) | ||
| 35 | #define MC_INT_SECURITY_VIOLATION BIT(MC_INT_ERR_SHIFT + 2) | ||
| 36 | #define MC_INT_ARBITRATION_EMEM BIT(MC_INT_ERR_SHIFT + 3) | ||
| 37 | #define MC_INT_INVALID_SMMU_PAGE BIT(MC_INT_ERR_SHIFT + 4) | ||
| 38 | |||
| 39 | #define MC_ERR_STATUS 0x8 | ||
| 40 | #define MC_ERR_ADR 0xc | ||
| 41 | |||
| 42 | #define MC_ERR_TYPE_SHIFT 28 | ||
| 43 | #define MC_ERR_TYPE_MASK (7 << MC_ERR_TYPE_SHIFT) | ||
| 44 | #define MC_ERR_TYPE_DECERR_EMEM 2 | ||
| 45 | #define MC_ERR_TYPE_SECURITY_TRUSTZONE 3 | ||
| 46 | #define MC_ERR_TYPE_SECURITY_CARVEOUT 4 | ||
| 47 | #define MC_ERR_TYPE_INVALID_SMMU_PAGE 6 | ||
| 48 | |||
| 49 | #define MC_ERR_INVALID_SMMU_PAGE_SHIFT 25 | ||
| 50 | #define MC_ERR_INVALID_SMMU_PAGE_MASK (7 << MC_ERR_INVALID_SMMU_PAGE_SHIFT) | ||
| 51 | #define MC_ERR_RW_SHIFT 16 | ||
| 52 | #define MC_ERR_RW BIT(MC_ERR_RW_SHIFT) | ||
| 53 | #define MC_ERR_SECURITY BIT(MC_ERR_RW_SHIFT + 1) | ||
| 54 | |||
| 55 | #define SECURITY_VIOLATION_TYPE BIT(30) /* 0=TRUSTZONE, 1=CARVEOUT */ | ||
| 56 | |||
| 57 | #define MC_EMEM_ARB_CFG 0x90 | ||
| 58 | #define MC_EMEM_ARB_OUTSTANDING_REQ 0x94 | ||
| 59 | #define MC_EMEM_ARB_TIMING_RCD 0x98 | ||
| 60 | #define MC_EMEM_ARB_TIMING_RP 0x9c | ||
| 61 | #define MC_EMEM_ARB_TIMING_RC 0xa0 | ||
| 62 | #define MC_EMEM_ARB_TIMING_RAS 0xa4 | ||
| 63 | #define MC_EMEM_ARB_TIMING_FAW 0xa8 | ||
| 64 | #define MC_EMEM_ARB_TIMING_RRD 0xac | ||
| 65 | #define MC_EMEM_ARB_TIMING_RAP2PRE 0xb0 | ||
| 66 | #define MC_EMEM_ARB_TIMING_WAP2PRE 0xb4 | ||
| 67 | #define MC_EMEM_ARB_TIMING_R2R 0xb8 | ||
| 68 | #define MC_EMEM_ARB_TIMING_W2W 0xbc | ||
| 69 | #define MC_EMEM_ARB_TIMING_R2W 0xc0 | ||
| 70 | #define MC_EMEM_ARB_TIMING_W2R 0xc4 | ||
| 71 | |||
| 72 | #define MC_EMEM_ARB_DA_TURNS 0xd0 | ||
| 73 | #define MC_EMEM_ARB_DA_COVERS 0xd4 | ||
| 74 | #define MC_EMEM_ARB_MISC0 0xd8 | ||
| 75 | #define MC_EMEM_ARB_MISC1 0xdc | ||
| 76 | |||
| 77 | #define MC_EMEM_ARB_RING3_THROTTLE 0xe4 | ||
| 78 | #define MC_EMEM_ARB_OVERRIDE 0xe8 | ||
| 79 | |||
| 80 | #define MC_TIMING_CONTROL 0xfc | ||
| 81 | |||
| 82 | #define MC_CLIENT_ID_MASK 0x7f | ||
| 83 | |||
| 84 | #define NUM_MC_REG_BANKS 4 | ||
| 85 | |||
| 86 | struct tegra30_mc { | ||
| 87 | void __iomem *regs[NUM_MC_REG_BANKS]; | ||
| 88 | struct device *dev; | ||
| 89 | u32 ctx[0]; | ||
| 90 | }; | ||
| 91 | |||
| 92 | static inline u32 mc_readl(struct tegra30_mc *mc, u32 offs) | ||
| 93 | { | ||
| 94 | u32 val = 0; | ||
| 95 | |||
| 96 | if (offs < 0x10) | ||
| 97 | val = readl(mc->regs[0] + offs); | ||
| 98 | if (offs < 0x1f0) | ||
| 99 | val = readl(mc->regs[1] + offs - 0x3c); | ||
| 100 | if (offs < 0x228) | ||
| 101 | val = readl(mc->regs[2] + offs - 0x200); | ||
| 102 | if (offs < 0x400) | ||
| 103 | val = readl(mc->regs[3] + offs - 0x284); | ||
| 104 | |||
| 105 | return val; | ||
| 106 | } | ||
| 107 | |||
| 108 | static inline void mc_writel(struct tegra30_mc *mc, u32 val, u32 offs) | ||
| 109 | { | ||
| 110 | if (offs < 0x10) { | ||
| 111 | writel(val, mc->regs[0] + offs); | ||
| 112 | return; | ||
| 113 | } | ||
| 114 | if (offs < 0x1f0) { | ||
| 115 | writel(val, mc->regs[1] + offs - 0x3c); | ||
| 116 | return; | ||
| 117 | } | ||
| 118 | if (offs < 0x228) { | ||
| 119 | writel(val, mc->regs[2] + offs - 0x200); | ||
| 120 | return; | ||
| 121 | } | ||
| 122 | if (offs < 0x400) { | ||
| 123 | writel(val, mc->regs[3] + offs - 0x284); | ||
| 124 | return; | ||
| 125 | } | ||
| 126 | } | ||
| 127 | |||
| 128 | static const char * const tegra30_mc_client[] = { | ||
| 129 | "csr_ptcr", | ||
| 130 | "cbr_display0a", | ||
| 131 | "cbr_display0ab", | ||
| 132 | "cbr_display0b", | ||
| 133 | "cbr_display0bb", | ||
| 134 | "cbr_display0c", | ||
| 135 | "cbr_display0cb", | ||
| 136 | "cbr_display1b", | ||
| 137 | "cbr_display1bb", | ||
| 138 | "cbr_eppup", | ||
| 139 | "cbr_g2pr", | ||
| 140 | "cbr_g2sr", | ||
| 141 | "cbr_mpeunifbr", | ||
| 142 | "cbr_viruv", | ||
| 143 | "csr_afir", | ||
| 144 | "csr_avpcarm7r", | ||
| 145 | "csr_displayhc", | ||
| 146 | "csr_displayhcb", | ||
| 147 | "csr_fdcdrd", | ||
| 148 | "csr_fdcdrd2", | ||
| 149 | "csr_g2dr", | ||
| 150 | "csr_hdar", | ||
| 151 | "csr_host1xdmar", | ||
| 152 | "csr_host1xr", | ||
| 153 | "csr_idxsrd", | ||
| 154 | "csr_idxsrd2", | ||
| 155 | "csr_mpe_ipred", | ||
| 156 | "csr_mpeamemrd", | ||
| 157 | "csr_mpecsrd", | ||
| 158 | "csr_ppcsahbdmar", | ||
| 159 | "csr_ppcsahbslvr", | ||
| 160 | "csr_satar", | ||
| 161 | "csr_texsrd", | ||
| 162 | "csr_texsrd2", | ||
| 163 | "csr_vdebsevr", | ||
| 164 | "csr_vdember", | ||
| 165 | "csr_vdemcer", | ||
| 166 | "csr_vdetper", | ||
| 167 | "csr_mpcorelpr", | ||
| 168 | "csr_mpcorer", | ||
| 169 | "cbw_eppu", | ||
| 170 | "cbw_eppv", | ||
| 171 | "cbw_eppy", | ||
| 172 | "cbw_mpeunifbw", | ||
| 173 | "cbw_viwsb", | ||
| 174 | "cbw_viwu", | ||
| 175 | "cbw_viwv", | ||
| 176 | "cbw_viwy", | ||
| 177 | "ccw_g2dw", | ||
| 178 | "csw_afiw", | ||
| 179 | "csw_avpcarm7w", | ||
| 180 | "csw_fdcdwr", | ||
| 181 | "csw_fdcdwr2", | ||
| 182 | "csw_hdaw", | ||
| 183 | "csw_host1xw", | ||
| 184 | "csw_ispw", | ||
| 185 | "csw_mpcorelpw", | ||
| 186 | "csw_mpcorew", | ||
| 187 | "csw_mpecswr", | ||
| 188 | "csw_ppcsahbdmaw", | ||
| 189 | "csw_ppcsahbslvw", | ||
| 190 | "csw_sataw", | ||
| 191 | "csw_vdebsevw", | ||
| 192 | "csw_vdedbgw", | ||
| 193 | "csw_vdembew", | ||
| 194 | "csw_vdetpmw", | ||
| 195 | }; | ||
| 196 | |||
| 197 | static void tegra30_mc_decode(struct tegra30_mc *mc, int n) | ||
| 198 | { | ||
| 199 | u32 err, addr; | ||
| 200 | const char * const mc_int_err[] = { | ||
| 201 | "MC_DECERR", | ||
| 202 | "Unknown", | ||
| 203 | "MC_SECURITY_ERR", | ||
| 204 | "MC_ARBITRATION_EMEM", | ||
| 205 | "MC_SMMU_ERR", | ||
| 206 | }; | ||
| 207 | const char * const err_type[] = { | ||
| 208 | "Unknown", | ||
| 209 | "Unknown", | ||
| 210 | "DECERR_EMEM", | ||
| 211 | "SECURITY_TRUSTZONE", | ||
| 212 | "SECURITY_CARVEOUT", | ||
| 213 | "Unknown", | ||
| 214 | "INVALID_SMMU_PAGE", | ||
| 215 | "Unknown", | ||
| 216 | }; | ||
| 217 | char attr[6]; | ||
| 218 | int cid, perm, type, idx; | ||
| 219 | const char *client = "Unknown"; | ||
| 220 | |||
| 221 | idx = n - MC_INT_ERR_SHIFT; | ||
| 222 | if ((idx < 0) || (idx >= ARRAY_SIZE(mc_int_err)) || (idx == 1)) { | ||
| 223 | dev_err_ratelimited(mc->dev, "Unknown interrupt status %08lx\n", | ||
| 224 | BIT(n)); | ||
| 225 | return; | ||
| 226 | } | ||
| 227 | |||
| 228 | err = readl(mc + MC_ERR_STATUS); | ||
| 229 | |||
| 230 | type = (err & MC_ERR_TYPE_MASK) >> MC_ERR_TYPE_SHIFT; | ||
| 231 | perm = (err & MC_ERR_INVALID_SMMU_PAGE_MASK) >> | ||
| 232 | MC_ERR_INVALID_SMMU_PAGE_SHIFT; | ||
| 233 | if (type == MC_ERR_TYPE_INVALID_SMMU_PAGE) | ||
| 234 | sprintf(attr, "%c-%c-%c", | ||
| 235 | (perm & BIT(2)) ? 'R' : '-', | ||
| 236 | (perm & BIT(1)) ? 'W' : '-', | ||
| 237 | (perm & BIT(0)) ? 'S' : '-'); | ||
| 238 | else | ||
| 239 | attr[0] = '\0'; | ||
| 240 | |||
| 241 | cid = err & MC_CLIENT_ID_MASK; | ||
| 242 | if (cid < ARRAY_SIZE(tegra30_mc_client)) | ||
| 243 | client = tegra30_mc_client[cid]; | ||
| 244 | |||
| 245 | addr = readl(mc + MC_ERR_ADR); | ||
| 246 | |||
| 247 | dev_err_ratelimited(mc->dev, "%s (0x%08x): 0x%08x %s (%s %s %s %s)\n", | ||
| 248 | mc_int_err[idx], err, addr, client, | ||
| 249 | (err & MC_ERR_SECURITY) ? "secure" : "non-secure", | ||
| 250 | (err & MC_ERR_RW) ? "write" : "read", | ||
| 251 | err_type[type], attr); | ||
| 252 | } | ||
| 253 | |||
| 254 | static const u32 tegra30_mc_ctx[] = { | ||
| 255 | MC_EMEM_ARB_CFG, | ||
| 256 | MC_EMEM_ARB_OUTSTANDING_REQ, | ||
| 257 | MC_EMEM_ARB_TIMING_RCD, | ||
| 258 | MC_EMEM_ARB_TIMING_RP, | ||
| 259 | MC_EMEM_ARB_TIMING_RC, | ||
| 260 | MC_EMEM_ARB_TIMING_RAS, | ||
| 261 | MC_EMEM_ARB_TIMING_FAW, | ||
| 262 | MC_EMEM_ARB_TIMING_RRD, | ||
| 263 | MC_EMEM_ARB_TIMING_RAP2PRE, | ||
| 264 | MC_EMEM_ARB_TIMING_WAP2PRE, | ||
| 265 | MC_EMEM_ARB_TIMING_R2R, | ||
| 266 | MC_EMEM_ARB_TIMING_W2W, | ||
| 267 | MC_EMEM_ARB_TIMING_R2W, | ||
| 268 | MC_EMEM_ARB_TIMING_W2R, | ||
| 269 | MC_EMEM_ARB_DA_TURNS, | ||
| 270 | MC_EMEM_ARB_DA_COVERS, | ||
| 271 | MC_EMEM_ARB_MISC0, | ||
| 272 | MC_EMEM_ARB_MISC1, | ||
| 273 | MC_EMEM_ARB_RING3_THROTTLE, | ||
| 274 | MC_EMEM_ARB_OVERRIDE, | ||
| 275 | MC_INTMASK, | ||
| 276 | }; | ||
| 277 | |||
| 278 | static int tegra30_mc_suspend(struct device *dev) | ||
| 279 | { | ||
| 280 | int i; | ||
| 281 | struct tegra30_mc *mc = dev_get_drvdata(dev); | ||
| 282 | |||
| 283 | for (i = 0; i < ARRAY_SIZE(tegra30_mc_ctx); i++) | ||
| 284 | mc->ctx[i] = mc_readl(mc, tegra30_mc_ctx[i]); | ||
| 285 | return 0; | ||
| 286 | } | ||
| 287 | |||
| 288 | static int tegra30_mc_resume(struct device *dev) | ||
| 289 | { | ||
| 290 | int i; | ||
| 291 | struct tegra30_mc *mc = dev_get_drvdata(dev); | ||
| 292 | |||
| 293 | for (i = 0; i < ARRAY_SIZE(tegra30_mc_ctx); i++) | ||
| 294 | mc_writel(mc, mc->ctx[i], tegra30_mc_ctx[i]); | ||
| 295 | |||
| 296 | mc_writel(mc, 1, MC_TIMING_CONTROL); | ||
| 297 | /* Read-back to ensure that write reached */ | ||
| 298 | mc_readl(mc, MC_TIMING_CONTROL); | ||
| 299 | return 0; | ||
| 300 | } | ||
| 301 | |||
| 302 | static UNIVERSAL_DEV_PM_OPS(tegra30_mc_pm, | ||
| 303 | tegra30_mc_suspend, | ||
| 304 | tegra30_mc_resume, NULL); | ||
| 305 | |||
| 306 | static const struct of_device_id tegra30_mc_of_match[] __devinitconst = { | ||
| 307 | { .compatible = "nvidia,tegra30-mc", }, | ||
| 308 | {}, | ||
| 309 | }; | ||
| 310 | |||
| 311 | static irqreturn_t tegra30_mc_isr(int irq, void *data) | ||
| 312 | { | ||
| 313 | u32 stat, mask, bit; | ||
| 314 | struct tegra30_mc *mc = data; | ||
| 315 | |||
| 316 | stat = mc_readl(mc, MC_INTSTATUS); | ||
| 317 | mask = mc_readl(mc, MC_INTMASK); | ||
| 318 | mask &= stat; | ||
| 319 | if (!mask) | ||
| 320 | return IRQ_NONE; | ||
| 321 | while ((bit = ffs(mask)) != 0) | ||
| 322 | tegra30_mc_decode(mc, bit - 1); | ||
| 323 | mc_writel(mc, stat, MC_INTSTATUS); | ||
| 324 | return IRQ_HANDLED; | ||
| 325 | } | ||
| 326 | |||
| 327 | static int __devinit tegra30_mc_probe(struct platform_device *pdev) | ||
| 328 | { | ||
| 329 | struct resource *irq; | ||
| 330 | struct tegra30_mc *mc; | ||
| 331 | size_t bytes; | ||
| 332 | int err, i; | ||
| 333 | u32 intmask; | ||
| 334 | |||
| 335 | bytes = sizeof(*mc) + sizeof(u32) * ARRAY_SIZE(tegra30_mc_ctx); | ||
| 336 | mc = devm_kzalloc(&pdev->dev, bytes, GFP_KERNEL); | ||
| 337 | if (!mc) | ||
| 338 | return -ENOMEM; | ||
| 339 | mc->dev = &pdev->dev; | ||
| 340 | |||
| 341 | for (i = 0; i < ARRAY_SIZE(mc->regs); i++) { | ||
| 342 | struct resource *res; | ||
| 343 | |||
| 344 | res = platform_get_resource(pdev, IORESOURCE_MEM, i); | ||
| 345 | if (!res) | ||
| 346 | return -ENODEV; | ||
| 347 | mc->regs[i] = devm_request_and_ioremap(&pdev->dev, res); | ||
| 348 | if (!mc->regs[i]) | ||
| 349 | return -EBUSY; | ||
| 350 | } | ||
| 351 | |||
| 352 | irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
| 353 | if (!irq) | ||
| 354 | return -ENODEV; | ||
| 355 | err = devm_request_irq(&pdev->dev, irq->start, tegra30_mc_isr, | ||
| 356 | IRQF_SHARED, dev_name(&pdev->dev), mc); | ||
| 357 | if (err) | ||
| 358 | return -ENODEV; | ||
| 359 | |||
| 360 | platform_set_drvdata(pdev, mc); | ||
| 361 | |||
| 362 | intmask = MC_INT_INVALID_SMMU_PAGE | | ||
| 363 | MC_INT_DECERR_EMEM | MC_INT_SECURITY_VIOLATION; | ||
| 364 | mc_writel(mc, intmask, MC_INTMASK); | ||
| 365 | return 0; | ||
| 366 | } | ||
| 367 | |||
| 368 | static struct platform_driver tegra30_mc_driver = { | ||
| 369 | .probe = tegra30_mc_probe, | ||
| 370 | .driver = { | ||
| 371 | .name = DRV_NAME, | ||
| 372 | .owner = THIS_MODULE, | ||
| 373 | .of_match_table = tegra30_mc_of_match, | ||
| 374 | .pm = &tegra30_mc_pm, | ||
| 375 | }, | ||
| 376 | }; | ||
| 377 | module_platform_driver(tegra30_mc_driver); | ||
| 378 | |||
| 379 | MODULE_AUTHOR("Hiroshi DOYU <hdoyu@nvidia.com>"); | ||
| 380 | MODULE_DESCRIPTION("Tegra30 MC driver"); | ||
| 381 | MODULE_LICENSE("GPL v2"); | ||
| 382 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 968469555956..757fbd0f2a14 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
| @@ -508,14 +508,6 @@ config USB_SWITCH_FSA9480 | |||
| 508 | stereo and mono audio, video, microphone and UART data to use | 508 | stereo and mono audio, video, microphone and UART data to use |
| 509 | a common connector port. | 509 | a common connector port. |
| 510 | 510 | ||
| 511 | config MAX8997_MUIC | ||
| 512 | tristate "MAX8997 MUIC Support" | ||
| 513 | depends on MFD_MAX8997 | ||
| 514 | help | ||
| 515 | If you say yes here you get support for the MUIC device of | ||
| 516 | Maxim MAX8997 PMIC. | ||
| 517 | The MAX8997 MUIC is a USB port accessory detector and switch. | ||
| 518 | |||
| 519 | source "drivers/misc/c2port/Kconfig" | 511 | source "drivers/misc/c2port/Kconfig" |
| 520 | source "drivers/misc/eeprom/Kconfig" | 512 | source "drivers/misc/eeprom/Kconfig" |
| 521 | source "drivers/misc/cb710/Kconfig" | 513 | source "drivers/misc/cb710/Kconfig" |
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 509d0569dc04..162861788c6d 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile | |||
| @@ -50,4 +50,3 @@ obj-y += lis3lv02d/ | |||
| 50 | obj-y += carma/ | 50 | obj-y += carma/ |
| 51 | obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o | 51 | obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o |
| 52 | obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/ | 52 | obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/ |
| 53 | obj-$(CONFIG_MAX8997_MUIC) += max8997-muic.o | ||
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 402956321d33..5abffe58a9d2 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c | |||
| @@ -2075,7 +2075,7 @@ struct parport *parport_pc_probe_port(unsigned long int base, | |||
| 2075 | 2075 | ||
| 2076 | printk(KERN_INFO "%s: PC-style at 0x%lx", p->name, p->base); | 2076 | printk(KERN_INFO "%s: PC-style at 0x%lx", p->name, p->base); |
| 2077 | if (p->base_hi && priv->ecr) | 2077 | if (p->base_hi && priv->ecr) |
| 2078 | printk(" (0x%lx)", p->base_hi); | 2078 | printk(KERN_CONT " (0x%lx)", p->base_hi); |
| 2079 | if (p->irq == PARPORT_IRQ_AUTO) { | 2079 | if (p->irq == PARPORT_IRQ_AUTO) { |
| 2080 | p->irq = PARPORT_IRQ_NONE; | 2080 | p->irq = PARPORT_IRQ_NONE; |
| 2081 | parport_irq_probe(p); | 2081 | parport_irq_probe(p); |
| @@ -2086,7 +2086,7 @@ struct parport *parport_pc_probe_port(unsigned long int base, | |||
| 2086 | p->irq = PARPORT_IRQ_NONE; | 2086 | p->irq = PARPORT_IRQ_NONE; |
| 2087 | } | 2087 | } |
| 2088 | if (p->irq != PARPORT_IRQ_NONE) { | 2088 | if (p->irq != PARPORT_IRQ_NONE) { |
| 2089 | printk(", irq %d", p->irq); | 2089 | printk(KERN_CONT ", irq %d", p->irq); |
| 2090 | priv->ctr_writable |= 0x10; | 2090 | priv->ctr_writable |= 0x10; |
| 2091 | 2091 | ||
| 2092 | if (p->dma == PARPORT_DMA_AUTO) { | 2092 | if (p->dma == PARPORT_DMA_AUTO) { |
| @@ -2110,21 +2110,21 @@ struct parport *parport_pc_probe_port(unsigned long int base, | |||
| 2110 | /* p->ops->ecp_read_data = parport_pc_ecp_read_block_pio; */ | 2110 | /* p->ops->ecp_read_data = parport_pc_ecp_read_block_pio; */ |
| 2111 | #endif /* IEEE 1284 support */ | 2111 | #endif /* IEEE 1284 support */ |
| 2112 | if (p->dma != PARPORT_DMA_NONE) { | 2112 | if (p->dma != PARPORT_DMA_NONE) { |
| 2113 | printk(", dma %d", p->dma); | 2113 | printk(KERN_CONT ", dma %d", p->dma); |
| 2114 | p->modes |= PARPORT_MODE_DMA; | 2114 | p->modes |= PARPORT_MODE_DMA; |
| 2115 | } else | 2115 | } else |
| 2116 | printk(", using FIFO"); | 2116 | printk(KERN_CONT ", using FIFO"); |
| 2117 | } else | 2117 | } else |
| 2118 | /* We can't use the DMA channel after all. */ | 2118 | /* We can't use the DMA channel after all. */ |
| 2119 | p->dma = PARPORT_DMA_NONE; | 2119 | p->dma = PARPORT_DMA_NONE; |
| 2120 | #endif /* Allowed to use FIFO/DMA */ | 2120 | #endif /* Allowed to use FIFO/DMA */ |
| 2121 | 2121 | ||
| 2122 | printk(" ["); | 2122 | printk(KERN_CONT " ["); |
| 2123 | 2123 | ||
| 2124 | #define printmode(x) \ | 2124 | #define printmode(x) \ |
| 2125 | {\ | 2125 | {\ |
| 2126 | if (p->modes & PARPORT_MODE_##x) {\ | 2126 | if (p->modes & PARPORT_MODE_##x) {\ |
| 2127 | printk("%s%s", f ? "," : "", #x);\ | 2127 | printk(KERN_CONT "%s%s", f ? "," : "", #x);\ |
| 2128 | f++;\ | 2128 | f++;\ |
| 2129 | } \ | 2129 | } \ |
| 2130 | } | 2130 | } |
| @@ -2140,9 +2140,9 @@ struct parport *parport_pc_probe_port(unsigned long int base, | |||
| 2140 | } | 2140 | } |
| 2141 | #undef printmode | 2141 | #undef printmode |
| 2142 | #ifndef CONFIG_PARPORT_1284 | 2142 | #ifndef CONFIG_PARPORT_1284 |
| 2143 | printk("(,...)"); | 2143 | printk(KERN_CONT "(,...)"); |
| 2144 | #endif /* CONFIG_PARPORT_1284 */ | 2144 | #endif /* CONFIG_PARPORT_1284 */ |
| 2145 | printk("]\n"); | 2145 | printk(KERN_CONT "]\n"); |
| 2146 | if (probedirq != PARPORT_IRQ_NONE) | 2146 | if (probedirq != PARPORT_IRQ_NONE) |
| 2147 | printk(KERN_INFO "%s: irq %d detected\n", p->name, probedirq); | 2147 | printk(KERN_INFO "%s: irq %d detected\n", p->name, probedirq); |
| 2148 | 2148 | ||
diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index eb1dee26bda3..c706635f3f82 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig | |||
| @@ -53,8 +53,6 @@ config ANDROID_LOW_MEMORY_KILLER | |||
| 53 | ---help--- | 53 | ---help--- |
| 54 | Register processes to be killed when memory is low | 54 | Register processes to be killed when memory is low |
| 55 | 55 | ||
| 56 | source "drivers/staging/android/switch/Kconfig" | ||
| 57 | |||
| 58 | config ANDROID_INTF_ALARM | 56 | config ANDROID_INTF_ALARM |
| 59 | bool "Android alarm driver" | 57 | bool "Android alarm driver" |
| 60 | depends on RTC_CLASS | 58 | depends on RTC_CLASS |
| @@ -80,7 +78,6 @@ config ANDROID_ALARM_OLDDRV_COMPAT | |||
| 80 | Provides preprocessor alias to aid compatability with | 78 | Provides preprocessor alias to aid compatability with |
| 81 | older out-of-tree drivers that use the Android Alarm | 79 | older out-of-tree drivers that use the Android Alarm |
| 82 | in-kernel API. This will be removed eventually. | 80 | in-kernel API. This will be removed eventually. |
| 83 | |||
| 84 | endif # if ANDROID | 81 | endif # if ANDROID |
| 85 | 82 | ||
| 86 | endmenu | 83 | endmenu |
diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile index 9b6c9ed91f69..045d17bde524 100644 --- a/drivers/staging/android/Makefile +++ b/drivers/staging/android/Makefile | |||
| @@ -6,6 +6,5 @@ obj-$(CONFIG_ANDROID_RAM_CONSOLE) += ram_console.o | |||
| 6 | obj-$(CONFIG_ANDROID_TIMED_OUTPUT) += timed_output.o | 6 | obj-$(CONFIG_ANDROID_TIMED_OUTPUT) += timed_output.o |
| 7 | obj-$(CONFIG_ANDROID_TIMED_GPIO) += timed_gpio.o | 7 | obj-$(CONFIG_ANDROID_TIMED_GPIO) += timed_gpio.o |
| 8 | obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o | 8 | obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o |
| 9 | obj-$(CONFIG_ANDROID_SWITCH) += switch/ | ||
| 10 | obj-$(CONFIG_ANDROID_INTF_ALARM) += alarm.o | 9 | obj-$(CONFIG_ANDROID_INTF_ALARM) += alarm.o |
| 11 | obj-$(CONFIG_ANDROID_INTF_ALARM_DEV) += alarm-dev.o | 10 | obj-$(CONFIG_ANDROID_INTF_ALARM_DEV) += alarm-dev.o |
diff --git a/drivers/staging/android/switch/Kconfig b/drivers/staging/android/switch/Kconfig deleted file mode 100644 index 36846f62f4bc..000000000000 --- a/drivers/staging/android/switch/Kconfig +++ /dev/null | |||
| @@ -1,11 +0,0 @@ | |||
| 1 | menuconfig ANDROID_SWITCH | ||
| 2 | tristate "Android Switch class support" | ||
| 3 | help | ||
| 4 | Say Y here to enable Android switch class support. This allows | ||
| 5 | monitoring switches by userspace via sysfs and uevent. | ||
| 6 | |||
| 7 | config ANDROID_SWITCH_GPIO | ||
| 8 | tristate "Android GPIO Switch support" | ||
| 9 | depends on GENERIC_GPIO && ANDROID_SWITCH | ||
| 10 | help | ||
| 11 | Say Y here to enable GPIO based switch support. | ||
diff --git a/drivers/staging/android/switch/Makefile b/drivers/staging/android/switch/Makefile deleted file mode 100644 index d76bfdcedfaf..000000000000 --- a/drivers/staging/android/switch/Makefile +++ /dev/null | |||
| @@ -1,4 +0,0 @@ | |||
| 1 | # Android Switch Class Driver | ||
| 2 | obj-$(CONFIG_ANDROID_SWITCH) += switch_class.o | ||
| 3 | obj-$(CONFIG_ANDROID_SWITCH_GPIO) += switch_gpio.o | ||
| 4 | |||
diff --git a/drivers/staging/android/switch/switch.h b/drivers/staging/android/switch/switch.h deleted file mode 100644 index 4fcb3109875a..000000000000 --- a/drivers/staging/android/switch/switch.h +++ /dev/null | |||
| @@ -1,53 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Switch class driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Google, Inc. | ||
| 5 | * Author: Mike Lockwood <lockwood@android.com> | ||
| 6 | * | ||
| 7 | * This software is licensed under the terms of the GNU General Public | ||
| 8 | * License version 2, as published by the Free Software Foundation, and | ||
| 9 | * may be copied, distributed, and modified under those terms. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef __LINUX_SWITCH_H__ | ||
| 19 | #define __LINUX_SWITCH_H__ | ||
| 20 | |||
| 21 | struct switch_dev { | ||
| 22 | const char *name; | ||
| 23 | struct device *dev; | ||
| 24 | int index; | ||
| 25 | int state; | ||
| 26 | |||
| 27 | ssize_t (*print_name)(struct switch_dev *sdev, char *buf); | ||
| 28 | ssize_t (*print_state)(struct switch_dev *sdev, char *buf); | ||
| 29 | }; | ||
| 30 | |||
| 31 | struct gpio_switch_platform_data { | ||
| 32 | const char *name; | ||
| 33 | unsigned gpio; | ||
| 34 | |||
| 35 | /* if NULL, switch_dev.name will be printed */ | ||
| 36 | const char *name_on; | ||
| 37 | const char *name_off; | ||
| 38 | /* if NULL, "0" or "1" will be printed */ | ||
| 39 | const char *state_on; | ||
| 40 | const char *state_off; | ||
| 41 | }; | ||
| 42 | |||
| 43 | extern int switch_dev_register(struct switch_dev *sdev); | ||
| 44 | extern void switch_dev_unregister(struct switch_dev *sdev); | ||
| 45 | |||
| 46 | static inline int switch_get_state(struct switch_dev *sdev) | ||
| 47 | { | ||
| 48 | return sdev->state; | ||
| 49 | } | ||
| 50 | |||
| 51 | extern void switch_set_state(struct switch_dev *sdev, int state); | ||
| 52 | |||
| 53 | #endif /* __LINUX_SWITCH_H__ */ | ||
diff --git a/drivers/staging/android/switch/switch_class.c b/drivers/staging/android/switch/switch_class.c deleted file mode 100644 index 74680446fc66..000000000000 --- a/drivers/staging/android/switch/switch_class.c +++ /dev/null | |||
| @@ -1,174 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * switch_class.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Google, Inc. | ||
| 5 | * Author: Mike Lockwood <lockwood@android.com> | ||
| 6 | * | ||
| 7 | * This software is licensed under the terms of the GNU General Public | ||
| 8 | * License version 2, as published by the Free Software Foundation, and | ||
| 9 | * may be copied, distributed, and modified under those terms. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/types.h> | ||
| 20 | #include <linux/init.h> | ||
| 21 | #include <linux/device.h> | ||
| 22 | #include <linux/fs.h> | ||
| 23 | #include <linux/err.h> | ||
| 24 | #include "switch.h" | ||
| 25 | |||
| 26 | struct class *switch_class; | ||
| 27 | static atomic_t device_count; | ||
| 28 | |||
| 29 | static ssize_t state_show(struct device *dev, struct device_attribute *attr, | ||
| 30 | char *buf) | ||
| 31 | { | ||
| 32 | struct switch_dev *sdev = (struct switch_dev *) | ||
| 33 | dev_get_drvdata(dev); | ||
| 34 | |||
| 35 | if (sdev->print_state) { | ||
| 36 | int ret = sdev->print_state(sdev, buf); | ||
| 37 | if (ret >= 0) | ||
| 38 | return ret; | ||
| 39 | } | ||
| 40 | return sprintf(buf, "%d\n", sdev->state); | ||
| 41 | } | ||
| 42 | |||
| 43 | static ssize_t name_show(struct device *dev, struct device_attribute *attr, | ||
| 44 | char *buf) | ||
| 45 | { | ||
| 46 | struct switch_dev *sdev = (struct switch_dev *) | ||
| 47 | dev_get_drvdata(dev); | ||
| 48 | |||
| 49 | if (sdev->print_name) { | ||
| 50 | int ret = sdev->print_name(sdev, buf); | ||
| 51 | if (ret >= 0) | ||
| 52 | return ret; | ||
| 53 | } | ||
| 54 | return sprintf(buf, "%s\n", sdev->name); | ||
| 55 | } | ||
| 56 | |||
| 57 | static DEVICE_ATTR(state, S_IRUGO | S_IWUSR, state_show, NULL); | ||
| 58 | static DEVICE_ATTR(name, S_IRUGO | S_IWUSR, name_show, NULL); | ||
| 59 | |||
| 60 | void switch_set_state(struct switch_dev *sdev, int state) | ||
| 61 | { | ||
| 62 | char name_buf[120]; | ||
| 63 | char state_buf[120]; | ||
| 64 | char *prop_buf; | ||
| 65 | char *envp[3]; | ||
| 66 | int env_offset = 0; | ||
| 67 | int length; | ||
| 68 | |||
| 69 | if (sdev->state != state) { | ||
| 70 | sdev->state = state; | ||
| 71 | |||
| 72 | prop_buf = (char *)get_zeroed_page(GFP_KERNEL); | ||
| 73 | if (prop_buf) { | ||
| 74 | length = name_show(sdev->dev, NULL, prop_buf); | ||
| 75 | if (length > 0) { | ||
| 76 | if (prop_buf[length - 1] == '\n') | ||
| 77 | prop_buf[length - 1] = 0; | ||
| 78 | snprintf(name_buf, sizeof(name_buf), | ||
| 79 | "SWITCH_NAME=%s", prop_buf); | ||
| 80 | envp[env_offset++] = name_buf; | ||
| 81 | } | ||
| 82 | length = state_show(sdev->dev, NULL, prop_buf); | ||
| 83 | if (length > 0) { | ||
| 84 | if (prop_buf[length - 1] == '\n') | ||
| 85 | prop_buf[length - 1] = 0; | ||
| 86 | snprintf(state_buf, sizeof(state_buf), | ||
| 87 | "SWITCH_STATE=%s", prop_buf); | ||
| 88 | envp[env_offset++] = state_buf; | ||
| 89 | } | ||
| 90 | envp[env_offset] = NULL; | ||
| 91 | kobject_uevent_env(&sdev->dev->kobj, KOBJ_CHANGE, envp); | ||
| 92 | free_page((unsigned long)prop_buf); | ||
| 93 | } else { | ||
| 94 | printk(KERN_ERR "out of memory in switch_set_state\n"); | ||
| 95 | kobject_uevent(&sdev->dev->kobj, KOBJ_CHANGE); | ||
| 96 | } | ||
| 97 | } | ||
| 98 | } | ||
| 99 | EXPORT_SYMBOL_GPL(switch_set_state); | ||
| 100 | |||
| 101 | static int create_switch_class(void) | ||
| 102 | { | ||
| 103 | if (!switch_class) { | ||
| 104 | switch_class = class_create(THIS_MODULE, "switch"); | ||
| 105 | if (IS_ERR(switch_class)) | ||
| 106 | return PTR_ERR(switch_class); | ||
| 107 | atomic_set(&device_count, 0); | ||
| 108 | } | ||
| 109 | |||
| 110 | return 0; | ||
| 111 | } | ||
| 112 | |||
| 113 | int switch_dev_register(struct switch_dev *sdev) | ||
| 114 | { | ||
| 115 | int ret; | ||
| 116 | |||
| 117 | if (!switch_class) { | ||
| 118 | ret = create_switch_class(); | ||
| 119 | if (ret < 0) | ||
| 120 | return ret; | ||
| 121 | } | ||
| 122 | |||
| 123 | sdev->index = atomic_inc_return(&device_count); | ||
| 124 | sdev->dev = device_create(switch_class, NULL, | ||
| 125 | MKDEV(0, sdev->index), NULL, sdev->name); | ||
| 126 | if (IS_ERR(sdev->dev)) | ||
| 127 | return PTR_ERR(sdev->dev); | ||
| 128 | |||
| 129 | ret = device_create_file(sdev->dev, &dev_attr_state); | ||
| 130 | if (ret < 0) | ||
| 131 | goto err_create_file_1; | ||
| 132 | ret = device_create_file(sdev->dev, &dev_attr_name); | ||
| 133 | if (ret < 0) | ||
| 134 | goto err_create_file_2; | ||
| 135 | |||
| 136 | dev_set_drvdata(sdev->dev, sdev); | ||
| 137 | sdev->state = 0; | ||
| 138 | return 0; | ||
| 139 | |||
| 140 | err_create_file_2: | ||
| 141 | device_remove_file(sdev->dev, &dev_attr_state); | ||
| 142 | err_create_file_1: | ||
| 143 | device_destroy(switch_class, MKDEV(0, sdev->index)); | ||
| 144 | printk(KERN_ERR "switch: Failed to register driver %s\n", sdev->name); | ||
| 145 | |||
| 146 | return ret; | ||
| 147 | } | ||
| 148 | EXPORT_SYMBOL_GPL(switch_dev_register); | ||
| 149 | |||
| 150 | void switch_dev_unregister(struct switch_dev *sdev) | ||
| 151 | { | ||
| 152 | device_remove_file(sdev->dev, &dev_attr_name); | ||
| 153 | device_remove_file(sdev->dev, &dev_attr_state); | ||
| 154 | device_destroy(switch_class, MKDEV(0, sdev->index)); | ||
| 155 | dev_set_drvdata(sdev->dev, NULL); | ||
| 156 | } | ||
| 157 | EXPORT_SYMBOL_GPL(switch_dev_unregister); | ||
| 158 | |||
| 159 | static int __init switch_class_init(void) | ||
| 160 | { | ||
| 161 | return create_switch_class(); | ||
| 162 | } | ||
| 163 | |||
| 164 | static void __exit switch_class_exit(void) | ||
| 165 | { | ||
| 166 | class_destroy(switch_class); | ||
| 167 | } | ||
| 168 | |||
| 169 | module_init(switch_class_init); | ||
| 170 | module_exit(switch_class_exit); | ||
| 171 | |||
| 172 | MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>"); | ||
| 173 | MODULE_DESCRIPTION("Switch class driver"); | ||
| 174 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/staging/android/switch/switch_gpio.c b/drivers/staging/android/switch/switch_gpio.c deleted file mode 100644 index 38b2c2f6004e..000000000000 --- a/drivers/staging/android/switch/switch_gpio.c +++ /dev/null | |||
| @@ -1,172 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * switch_gpio.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Google, Inc. | ||
| 5 | * Author: Mike Lockwood <lockwood@android.com> | ||
| 6 | * | ||
| 7 | * This software is licensed under the terms of the GNU General Public | ||
| 8 | * License version 2, as published by the Free Software Foundation, and | ||
| 9 | * may be copied, distributed, and modified under those terms. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/kernel.h> | ||
| 20 | #include <linux/init.h> | ||
| 21 | #include <linux/interrupt.h> | ||
| 22 | #include <linux/platform_device.h> | ||
| 23 | #include <linux/slab.h> | ||
| 24 | #include <linux/workqueue.h> | ||
| 25 | #include <linux/gpio.h> | ||
| 26 | #include "switch.h" | ||
| 27 | |||
| 28 | struct gpio_switch_data { | ||
| 29 | struct switch_dev sdev; | ||
| 30 | unsigned gpio; | ||
| 31 | const char *name_on; | ||
| 32 | const char *name_off; | ||
| 33 | const char *state_on; | ||
| 34 | const char *state_off; | ||
| 35 | int irq; | ||
| 36 | struct work_struct work; | ||
| 37 | }; | ||
| 38 | |||
| 39 | static void gpio_switch_work(struct work_struct *work) | ||
| 40 | { | ||
| 41 | int state; | ||
| 42 | struct gpio_switch_data *data = | ||
| 43 | container_of(work, struct gpio_switch_data, work); | ||
| 44 | |||
| 45 | state = gpio_get_value(data->gpio); | ||
| 46 | switch_set_state(&data->sdev, state); | ||
| 47 | } | ||
| 48 | |||
| 49 | static irqreturn_t gpio_irq_handler(int irq, void *dev_id) | ||
| 50 | { | ||
| 51 | struct gpio_switch_data *switch_data = | ||
| 52 | (struct gpio_switch_data *)dev_id; | ||
| 53 | |||
| 54 | schedule_work(&switch_data->work); | ||
| 55 | return IRQ_HANDLED; | ||
| 56 | } | ||
| 57 | |||
| 58 | static ssize_t switch_gpio_print_state(struct switch_dev *sdev, char *buf) | ||
| 59 | { | ||
| 60 | struct gpio_switch_data *switch_data = | ||
| 61 | container_of(sdev, struct gpio_switch_data, sdev); | ||
| 62 | const char *state; | ||
| 63 | if (switch_get_state(sdev)) | ||
| 64 | state = switch_data->state_on; | ||
| 65 | else | ||
| 66 | state = switch_data->state_off; | ||
| 67 | |||
| 68 | if (state) | ||
| 69 | return sprintf(buf, "%s\n", state); | ||
| 70 | return -1; | ||
| 71 | } | ||
| 72 | |||
| 73 | static int gpio_switch_probe(struct platform_device *pdev) | ||
| 74 | { | ||
| 75 | struct gpio_switch_platform_data *pdata = pdev->dev.platform_data; | ||
| 76 | struct gpio_switch_data *switch_data; | ||
| 77 | int ret = 0; | ||
| 78 | |||
| 79 | if (!pdata) | ||
| 80 | return -EBUSY; | ||
| 81 | |||
| 82 | switch_data = kzalloc(sizeof(struct gpio_switch_data), GFP_KERNEL); | ||
| 83 | if (!switch_data) | ||
| 84 | return -ENOMEM; | ||
| 85 | |||
| 86 | switch_data->sdev.name = pdata->name; | ||
| 87 | switch_data->gpio = pdata->gpio; | ||
| 88 | switch_data->name_on = pdata->name_on; | ||
| 89 | switch_data->name_off = pdata->name_off; | ||
| 90 | switch_data->state_on = pdata->state_on; | ||
| 91 | switch_data->state_off = pdata->state_off; | ||
| 92 | switch_data->sdev.print_state = switch_gpio_print_state; | ||
| 93 | |||
| 94 | ret = switch_dev_register(&switch_data->sdev); | ||
| 95 | if (ret < 0) | ||
| 96 | goto err_switch_dev_register; | ||
| 97 | |||
| 98 | ret = gpio_request(switch_data->gpio, pdev->name); | ||
| 99 | if (ret < 0) | ||
| 100 | goto err_request_gpio; | ||
| 101 | |||
| 102 | ret = gpio_direction_input(switch_data->gpio); | ||
| 103 | if (ret < 0) | ||
| 104 | goto err_set_gpio_input; | ||
| 105 | |||
| 106 | INIT_WORK(&switch_data->work, gpio_switch_work); | ||
| 107 | |||
| 108 | switch_data->irq = gpio_to_irq(switch_data->gpio); | ||
| 109 | if (switch_data->irq < 0) { | ||
| 110 | ret = switch_data->irq; | ||
| 111 | goto err_detect_irq_num_failed; | ||
| 112 | } | ||
| 113 | |||
| 114 | ret = request_irq(switch_data->irq, gpio_irq_handler, | ||
| 115 | IRQF_TRIGGER_LOW, pdev->name, switch_data); | ||
| 116 | if (ret < 0) | ||
| 117 | goto err_request_irq; | ||
| 118 | |||
| 119 | /* Perform initial detection */ | ||
| 120 | gpio_switch_work(&switch_data->work); | ||
| 121 | |||
| 122 | return 0; | ||
| 123 | |||
| 124 | err_request_irq: | ||
| 125 | err_detect_irq_num_failed: | ||
| 126 | err_set_gpio_input: | ||
| 127 | gpio_free(switch_data->gpio); | ||
| 128 | err_request_gpio: | ||
| 129 | switch_dev_unregister(&switch_data->sdev); | ||
| 130 | err_switch_dev_register: | ||
| 131 | kfree(switch_data); | ||
| 132 | |||
| 133 | return ret; | ||
| 134 | } | ||
| 135 | |||
| 136 | static int __devexit gpio_switch_remove(struct platform_device *pdev) | ||
| 137 | { | ||
| 138 | struct gpio_switch_data *switch_data = platform_get_drvdata(pdev); | ||
| 139 | |||
| 140 | cancel_work_sync(&switch_data->work); | ||
| 141 | gpio_free(switch_data->gpio); | ||
| 142 | switch_dev_unregister(&switch_data->sdev); | ||
| 143 | kfree(switch_data); | ||
| 144 | |||
| 145 | return 0; | ||
| 146 | } | ||
| 147 | |||
| 148 | static struct platform_driver gpio_switch_driver = { | ||
| 149 | .probe = gpio_switch_probe, | ||
| 150 | .remove = __devexit_p(gpio_switch_remove), | ||
| 151 | .driver = { | ||
| 152 | .name = "switch-gpio", | ||
| 153 | .owner = THIS_MODULE, | ||
| 154 | }, | ||
| 155 | }; | ||
| 156 | |||
| 157 | static int __init gpio_switch_init(void) | ||
| 158 | { | ||
| 159 | return platform_driver_register(&gpio_switch_driver); | ||
| 160 | } | ||
| 161 | |||
| 162 | static void __exit gpio_switch_exit(void) | ||
| 163 | { | ||
| 164 | platform_driver_unregister(&gpio_switch_driver); | ||
| 165 | } | ||
| 166 | |||
| 167 | module_init(gpio_switch_init); | ||
| 168 | module_exit(gpio_switch_exit); | ||
| 169 | |||
| 170 | MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>"); | ||
| 171 | MODULE_DESCRIPTION("GPIO Switch driver"); | ||
| 172 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/uio/uio_pdrv_genirq.c b/drivers/uio/uio_pdrv_genirq.c index b98371d93a92..42202cd83158 100644 --- a/drivers/uio/uio_pdrv_genirq.c +++ b/drivers/uio/uio_pdrv_genirq.c | |||
| @@ -146,6 +146,14 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev) | |||
| 146 | priv->flags = 0; /* interrupt is enabled to begin with */ | 146 | priv->flags = 0; /* interrupt is enabled to begin with */ |
| 147 | priv->pdev = pdev; | 147 | priv->pdev = pdev; |
| 148 | 148 | ||
| 149 | if (!uioinfo->irq) { | ||
| 150 | ret = platform_get_irq(pdev, 0); | ||
| 151 | if (ret < 0) { | ||
| 152 | dev_err(&pdev->dev, "failed to get IRQ\n"); | ||
| 153 | goto bad0; | ||
| 154 | } | ||
| 155 | uioinfo->irq = ret; | ||
| 156 | } | ||
| 149 | uiomem = &uioinfo->mem[0]; | 157 | uiomem = &uioinfo->mem[0]; |
| 150 | 158 | ||
| 151 | for (i = 0; i < pdev->num_resources; ++i) { | 159 | for (i = 0; i < pdev->num_resources; ++i) { |
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 566d9f94f735..9a56e3adf476 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c | |||
| @@ -73,7 +73,7 @@ set_bConfigurationValue(struct device *dev, struct device_attribute *attr, | |||
| 73 | return (value < 0) ? value : count; | 73 | return (value < 0) ? value : count; |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | static DEVICE_ATTR(bConfigurationValue, S_IRUGO | S_IWUSR, | 76 | static DEVICE_ATTR_IGNORE_LOCKDEP(bConfigurationValue, S_IRUGO | S_IWUSR, |
| 77 | show_bConfigurationValue, set_bConfigurationValue); | 77 | show_bConfigurationValue, set_bConfigurationValue); |
| 78 | 78 | ||
| 79 | /* String fields */ | 79 | /* String fields */ |
| @@ -595,7 +595,7 @@ static ssize_t usb_dev_authorized_store(struct device *dev, | |||
| 595 | return result < 0? result : size; | 595 | return result < 0? result : size; |
| 596 | } | 596 | } |
| 597 | 597 | ||
| 598 | static DEVICE_ATTR(authorized, 0644, | 598 | static DEVICE_ATTR_IGNORE_LOCKDEP(authorized, 0644, |
| 599 | usb_dev_authorized_show, usb_dev_authorized_store); | 599 | usb_dev_authorized_show, usb_dev_authorized_store); |
| 600 | 600 | ||
| 601 | /* "Safely remove a device" */ | 601 | /* "Safely remove a device" */ |
| @@ -618,7 +618,7 @@ static ssize_t usb_remove_store(struct device *dev, | |||
| 618 | usb_unlock_device(udev); | 618 | usb_unlock_device(udev); |
| 619 | return rc; | 619 | return rc; |
| 620 | } | 620 | } |
| 621 | static DEVICE_ATTR(remove, 0200, NULL, usb_remove_store); | 621 | static DEVICE_ATTR_IGNORE_LOCKDEP(remove, 0200, NULL, usb_remove_store); |
| 622 | 622 | ||
| 623 | 623 | ||
| 624 | static struct attribute *dev_attrs[] = { | 624 | static struct attribute *dev_attrs[] = { |
diff --git a/drivers/w1/slaves/w1_ds2408.c b/drivers/w1/slaves/w1_ds2408.c index 7c8cdb8aed26..8e813eed0f0a 100644 --- a/drivers/w1/slaves/w1_ds2408.c +++ b/drivers/w1/slaves/w1_ds2408.c | |||
| @@ -332,7 +332,6 @@ static struct bin_attribute w1_f29_sysfs_bin_files[NB_SYSFS_BIN_FILES] = { | |||
| 332 | }, | 332 | }, |
| 333 | .size = 1, | 333 | .size = 1, |
| 334 | .read = w1_f29_read_cond_search_mask, | 334 | .read = w1_f29_read_cond_search_mask, |
| 335 | .write = 0, | ||
| 336 | }, | 335 | }, |
| 337 | { | 336 | { |
| 338 | .attr = { | 337 | .attr = { |
| @@ -341,7 +340,6 @@ static struct bin_attribute w1_f29_sysfs_bin_files[NB_SYSFS_BIN_FILES] = { | |||
| 341 | }, | 340 | }, |
| 342 | .size = 1, | 341 | .size = 1, |
| 343 | .read = w1_f29_read_cond_search_polarity, | 342 | .read = w1_f29_read_cond_search_polarity, |
| 344 | .write = 0, | ||
| 345 | }, | 343 | }, |
| 346 | { | 344 | { |
| 347 | .attr = { | 345 | .attr = { |
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 9761950697b4..2f2e894ea0c8 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c | |||
| @@ -1027,7 +1027,7 @@ static int __init w1_init(void) | |||
| 1027 | retval = driver_register(&w1_slave_driver); | 1027 | retval = driver_register(&w1_slave_driver); |
| 1028 | if (retval) { | 1028 | if (retval) { |
| 1029 | printk(KERN_ERR | 1029 | printk(KERN_ERR |
| 1030 | "Failed to register master driver. err=%d.\n", | 1030 | "Failed to register slave driver. err=%d.\n", |
| 1031 | retval); | 1031 | retval); |
| 1032 | goto err_out_master_unregister; | 1032 | goto err_out_master_unregister; |
| 1033 | } | 1033 | } |
diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c index 3135b2c63998..e10acc237733 100644 --- a/drivers/w1/w1_io.c +++ b/drivers/w1/w1_io.c | |||
| @@ -31,6 +31,9 @@ | |||
| 31 | static int w1_delay_parm = 1; | 31 | static int w1_delay_parm = 1; |
| 32 | module_param_named(delay_coef, w1_delay_parm, int, 0); | 32 | module_param_named(delay_coef, w1_delay_parm, int, 0); |
| 33 | 33 | ||
| 34 | static int w1_disable_irqs = 0; | ||
| 35 | module_param_named(disable_irqs, w1_disable_irqs, int, 0); | ||
| 36 | |||
| 34 | static u8 w1_crc8_table[] = { | 37 | static u8 w1_crc8_table[] = { |
| 35 | 0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65, | 38 | 0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65, |
| 36 | 157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220, | 39 | 157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220, |
| @@ -79,6 +82,10 @@ static u8 w1_touch_bit(struct w1_master *dev, int bit) | |||
| 79 | */ | 82 | */ |
| 80 | static void w1_write_bit(struct w1_master *dev, int bit) | 83 | static void w1_write_bit(struct w1_master *dev, int bit) |
| 81 | { | 84 | { |
| 85 | unsigned long flags = 0; | ||
| 86 | |||
| 87 | if(w1_disable_irqs) local_irq_save(flags); | ||
| 88 | |||
| 82 | if (bit) { | 89 | if (bit) { |
| 83 | dev->bus_master->write_bit(dev->bus_master->data, 0); | 90 | dev->bus_master->write_bit(dev->bus_master->data, 0); |
| 84 | w1_delay(6); | 91 | w1_delay(6); |
| @@ -90,6 +97,8 @@ static void w1_write_bit(struct w1_master *dev, int bit) | |||
| 90 | dev->bus_master->write_bit(dev->bus_master->data, 1); | 97 | dev->bus_master->write_bit(dev->bus_master->data, 1); |
| 91 | w1_delay(10); | 98 | w1_delay(10); |
| 92 | } | 99 | } |
| 100 | |||
| 101 | if(w1_disable_irqs) local_irq_restore(flags); | ||
| 93 | } | 102 | } |
| 94 | 103 | ||
| 95 | /** | 104 | /** |
| @@ -158,7 +167,7 @@ EXPORT_SYMBOL_GPL(w1_write_8); | |||
| 158 | static u8 w1_read_bit(struct w1_master *dev) | 167 | static u8 w1_read_bit(struct w1_master *dev) |
| 159 | { | 168 | { |
| 160 | int result; | 169 | int result; |
| 161 | unsigned long flags; | 170 | unsigned long flags = 0; |
| 162 | 171 | ||
| 163 | /* sample timing is critical here */ | 172 | /* sample timing is critical here */ |
| 164 | local_irq_save(flags); | 173 | local_irq_save(flags); |
| @@ -318,6 +327,9 @@ EXPORT_SYMBOL_GPL(w1_read_block); | |||
| 318 | int w1_reset_bus(struct w1_master *dev) | 327 | int w1_reset_bus(struct w1_master *dev) |
| 319 | { | 328 | { |
| 320 | int result; | 329 | int result; |
| 330 | unsigned long flags = 0; | ||
| 331 | |||
| 332 | if(w1_disable_irqs) local_irq_save(flags); | ||
| 321 | 333 | ||
| 322 | if (dev->bus_master->reset_bus) | 334 | if (dev->bus_master->reset_bus) |
| 323 | result = dev->bus_master->reset_bus(dev->bus_master->data) & 0x1; | 335 | result = dev->bus_master->reset_bus(dev->bus_master->data) & 0x1; |
| @@ -330,19 +342,21 @@ int w1_reset_bus(struct w1_master *dev) | |||
| 330 | * cpu for such a short amount of time AND get it back in | 342 | * cpu for such a short amount of time AND get it back in |
| 331 | * the maximum amount of time. | 343 | * the maximum amount of time. |
| 332 | */ | 344 | */ |
| 333 | w1_delay(480); | 345 | w1_delay(500); |
| 334 | dev->bus_master->write_bit(dev->bus_master->data, 1); | 346 | dev->bus_master->write_bit(dev->bus_master->data, 1); |
| 335 | w1_delay(70); | 347 | w1_delay(70); |
| 336 | 348 | ||
| 337 | result = dev->bus_master->read_bit(dev->bus_master->data) & 0x1; | 349 | result = dev->bus_master->read_bit(dev->bus_master->data) & 0x1; |
| 338 | /* minmum 70 (above) + 410 = 480 us | 350 | /* minmum 70 (above) + 430 = 500 us |
| 339 | * There aren't any timing requirements between a reset and | 351 | * There aren't any timing requirements between a reset and |
| 340 | * the following transactions. Sleeping is safe here. | 352 | * the following transactions. Sleeping is safe here. |
| 341 | */ | 353 | */ |
| 342 | /* w1_delay(410); min required time */ | 354 | /* w1_delay(430); min required time */ |
| 343 | msleep(1); | 355 | msleep(1); |
| 344 | } | 356 | } |
| 345 | 357 | ||
| 358 | if(w1_disable_irqs) local_irq_restore(flags); | ||
| 359 | |||
| 346 | return result; | 360 | return result; |
| 347 | } | 361 | } |
| 348 | EXPORT_SYMBOL_GPL(w1_reset_bus); | 362 | EXPORT_SYMBOL_GPL(w1_reset_bus); |
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 35a36d39fa2c..e6bb9b2a4cbe 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
| @@ -132,6 +132,24 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd) | |||
| 132 | rb_erase(&sd->s_rb, &sd->s_parent->s_dir.children); | 132 | rb_erase(&sd->s_rb, &sd->s_parent->s_dir.children); |
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
| 136 | |||
| 137 | /* Test for attributes that want to ignore lockdep for read-locking */ | ||
| 138 | static bool ignore_lockdep(struct sysfs_dirent *sd) | ||
| 139 | { | ||
| 140 | return sysfs_type(sd) == SYSFS_KOBJ_ATTR && | ||
| 141 | sd->s_attr.attr->ignore_lockdep; | ||
| 142 | } | ||
| 143 | |||
| 144 | #else | ||
| 145 | |||
| 146 | static inline bool ignore_lockdep(struct sysfs_dirent *sd) | ||
| 147 | { | ||
| 148 | return true; | ||
| 149 | } | ||
| 150 | |||
| 151 | #endif | ||
| 152 | |||
| 135 | /** | 153 | /** |
| 136 | * sysfs_get_active - get an active reference to sysfs_dirent | 154 | * sysfs_get_active - get an active reference to sysfs_dirent |
| 137 | * @sd: sysfs_dirent to get an active reference to | 155 | * @sd: sysfs_dirent to get an active reference to |
| @@ -155,15 +173,17 @@ struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd) | |||
| 155 | return NULL; | 173 | return NULL; |
| 156 | 174 | ||
| 157 | t = atomic_cmpxchg(&sd->s_active, v, v + 1); | 175 | t = atomic_cmpxchg(&sd->s_active, v, v + 1); |
| 158 | if (likely(t == v)) { | 176 | if (likely(t == v)) |
| 159 | rwsem_acquire_read(&sd->dep_map, 0, 1, _RET_IP_); | 177 | break; |
| 160 | return sd; | ||
| 161 | } | ||
| 162 | if (t < 0) | 178 | if (t < 0) |
| 163 | return NULL; | 179 | return NULL; |
| 164 | 180 | ||
| 165 | cpu_relax(); | 181 | cpu_relax(); |
| 166 | } | 182 | } |
| 183 | |||
| 184 | if (likely(!ignore_lockdep(sd))) | ||
| 185 | rwsem_acquire_read(&sd->dep_map, 0, 1, _RET_IP_); | ||
| 186 | return sd; | ||
| 167 | } | 187 | } |
| 168 | 188 | ||
| 169 | /** | 189 | /** |
| @@ -180,7 +200,8 @@ void sysfs_put_active(struct sysfs_dirent *sd) | |||
| 180 | if (unlikely(!sd)) | 200 | if (unlikely(!sd)) |
| 181 | return; | 201 | return; |
| 182 | 202 | ||
| 183 | rwsem_release(&sd->dep_map, 1, _RET_IP_); | 203 | if (likely(!ignore_lockdep(sd))) |
| 204 | rwsem_release(&sd->dep_map, 1, _RET_IP_); | ||
| 184 | v = atomic_dec_return(&sd->s_active); | 205 | v = atomic_dec_return(&sd->s_active); |
| 185 | if (likely(v != SD_DEACTIVATED_BIAS)) | 206 | if (likely(v != SD_DEACTIVATED_BIAS)) |
| 186 | return; | 207 | return; |
| @@ -858,7 +879,6 @@ int sysfs_rename(struct sysfs_dirent *sd, | |||
| 858 | struct sysfs_dirent *new_parent_sd, const void *new_ns, | 879 | struct sysfs_dirent *new_parent_sd, const void *new_ns, |
| 859 | const char *new_name) | 880 | const char *new_name) |
| 860 | { | 881 | { |
| 861 | const char *dup_name = NULL; | ||
| 862 | int error; | 882 | int error; |
| 863 | 883 | ||
| 864 | mutex_lock(&sysfs_mutex); | 884 | mutex_lock(&sysfs_mutex); |
| @@ -875,11 +895,11 @@ int sysfs_rename(struct sysfs_dirent *sd, | |||
| 875 | /* rename sysfs_dirent */ | 895 | /* rename sysfs_dirent */ |
| 876 | if (strcmp(sd->s_name, new_name) != 0) { | 896 | if (strcmp(sd->s_name, new_name) != 0) { |
| 877 | error = -ENOMEM; | 897 | error = -ENOMEM; |
| 878 | new_name = dup_name = kstrdup(new_name, GFP_KERNEL); | 898 | new_name = kstrdup(new_name, GFP_KERNEL); |
| 879 | if (!new_name) | 899 | if (!new_name) |
| 880 | goto out; | 900 | goto out; |
| 881 | 901 | ||
| 882 | dup_name = sd->s_name; | 902 | kfree(sd->s_name); |
| 883 | sd->s_name = new_name; | 903 | sd->s_name = new_name; |
| 884 | } | 904 | } |
| 885 | 905 | ||
| @@ -895,7 +915,6 @@ int sysfs_rename(struct sysfs_dirent *sd, | |||
| 895 | error = 0; | 915 | error = 0; |
| 896 | out: | 916 | out: |
| 897 | mutex_unlock(&sysfs_mutex); | 917 | mutex_unlock(&sysfs_mutex); |
| 898 | kfree(dup_name); | ||
| 899 | return error; | 918 | return error; |
| 900 | } | 919 | } |
| 901 | 920 | ||
diff --git a/include/linux/device.h b/include/linux/device.h index 5ad17cccdd71..e04f5776f6d0 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
| 24 | #include <linux/pm.h> | 24 | #include <linux/pm.h> |
| 25 | #include <linux/atomic.h> | 25 | #include <linux/atomic.h> |
| 26 | #include <linux/ratelimit.h> | ||
| 26 | #include <asm/device.h> | 27 | #include <asm/device.h> |
| 27 | 28 | ||
| 28 | struct device; | 29 | struct device; |
| @@ -502,7 +503,10 @@ ssize_t device_store_int(struct device *dev, struct device_attribute *attr, | |||
| 502 | { __ATTR(_name, _mode, device_show_ulong, device_store_ulong), &(_var) } | 503 | { __ATTR(_name, _mode, device_show_ulong, device_store_ulong), &(_var) } |
| 503 | #define DEVICE_INT_ATTR(_name, _mode, _var) \ | 504 | #define DEVICE_INT_ATTR(_name, _mode, _var) \ |
| 504 | struct dev_ext_attribute dev_attr_##_name = \ | 505 | struct dev_ext_attribute dev_attr_##_name = \ |
| 505 | { __ATTR(_name, _mode, device_show_ulong, device_store_ulong), &(_var) } | 506 | { __ATTR(_name, _mode, device_show_int, device_store_int), &(_var) } |
| 507 | #define DEVICE_ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store) \ | ||
| 508 | struct device_attribute dev_attr_##_name = \ | ||
| 509 | __ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store) | ||
| 506 | 510 | ||
| 507 | extern int device_create_file(struct device *device, | 511 | extern int device_create_file(struct device *device, |
| 508 | const struct device_attribute *entry); | 512 | const struct device_attribute *entry); |
| @@ -541,6 +545,8 @@ extern void *devres_remove(struct device *dev, dr_release_t release, | |||
| 541 | dr_match_t match, void *match_data); | 545 | dr_match_t match, void *match_data); |
| 542 | extern int devres_destroy(struct device *dev, dr_release_t release, | 546 | extern int devres_destroy(struct device *dev, dr_release_t release, |
| 543 | dr_match_t match, void *match_data); | 547 | dr_match_t match, void *match_data); |
| 548 | extern int devres_release(struct device *dev, dr_release_t release, | ||
| 549 | dr_match_t match, void *match_data); | ||
| 544 | 550 | ||
| 545 | /* devres group */ | 551 | /* devres group */ |
| 546 | extern void * __must_check devres_open_group(struct device *dev, void *id, | 552 | extern void * __must_check devres_open_group(struct device *dev, void *id, |
| @@ -931,6 +937,32 @@ int _dev_info(const struct device *dev, const char *fmt, ...) | |||
| 931 | 937 | ||
| 932 | #endif | 938 | #endif |
| 933 | 939 | ||
| 940 | #define dev_level_ratelimited(dev_level, dev, fmt, ...) \ | ||
| 941 | do { \ | ||
| 942 | static DEFINE_RATELIMIT_STATE(_rs, \ | ||
| 943 | DEFAULT_RATELIMIT_INTERVAL, \ | ||
| 944 | DEFAULT_RATELIMIT_BURST); \ | ||
| 945 | if (__ratelimit(&_rs)) \ | ||
| 946 | dev_level(dev, fmt, ##__VA_ARGS__); \ | ||
| 947 | } while (0) | ||
| 948 | |||
| 949 | #define dev_emerg_ratelimited(dev, fmt, ...) \ | ||
| 950 | dev_level_ratelimited(dev_emerg, dev, fmt, ##__VA_ARGS__) | ||
| 951 | #define dev_alert_ratelimited(dev, fmt, ...) \ | ||
| 952 | dev_level_ratelimited(dev_alert, dev, fmt, ##__VA_ARGS__) | ||
| 953 | #define dev_crit_ratelimited(dev, fmt, ...) \ | ||
| 954 | dev_level_ratelimited(dev_crit, dev, fmt, ##__VA_ARGS__) | ||
| 955 | #define dev_err_ratelimited(dev, fmt, ...) \ | ||
| 956 | dev_level_ratelimited(dev_err, dev, fmt, ##__VA_ARGS__) | ||
| 957 | #define dev_warn_ratelimited(dev, fmt, ...) \ | ||
| 958 | dev_level_ratelimited(dev_warn, dev, fmt, ##__VA_ARGS__) | ||
| 959 | #define dev_notice_ratelimited(dev, fmt, ...) \ | ||
| 960 | dev_level_ratelimited(dev_notice, dev, fmt, ##__VA_ARGS__) | ||
| 961 | #define dev_info_ratelimited(dev, fmt, ...) \ | ||
| 962 | dev_level_ratelimited(dev_info, dev, fmt, ##__VA_ARGS__) | ||
| 963 | #define dev_dbg_ratelimited(dev, fmt, ...) \ | ||
| 964 | dev_level_ratelimited(dev_dbg, dev, fmt, ##__VA_ARGS__) | ||
| 965 | |||
| 934 | /* | 966 | /* |
| 935 | * Stupid hackaround for existing uses of non-printk uses dev_info | 967 | * Stupid hackaround for existing uses of non-printk uses dev_info |
| 936 | * | 968 | * |
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h index 7e3c53a900d8..c18257b0fa72 100644 --- a/include/linux/dynamic_debug.h +++ b/include/linux/dynamic_debug.h | |||
| @@ -17,8 +17,8 @@ struct _ddebug { | |||
| 17 | const char *format; | 17 | const char *format; |
| 18 | unsigned int lineno:18; | 18 | unsigned int lineno:18; |
| 19 | /* | 19 | /* |
| 20 | * The flags field controls the behaviour at the callsite. | 20 | * The flags field controls the behaviour at the callsite. |
| 21 | * The bits here are changed dynamically when the user | 21 | * The bits here are changed dynamically when the user |
| 22 | * writes commands to <debugfs>/dynamic_debug/control | 22 | * writes commands to <debugfs>/dynamic_debug/control |
| 23 | */ | 23 | */ |
| 24 | #define _DPRINTK_FLAGS_NONE 0 | 24 | #define _DPRINTK_FLAGS_NONE 0 |
| @@ -44,6 +44,9 @@ extern int ddebug_remove_module(const char *mod_name); | |||
| 44 | extern __printf(2, 3) | 44 | extern __printf(2, 3) |
| 45 | int __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...); | 45 | int __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...); |
| 46 | 46 | ||
| 47 | extern int ddebug_dyndbg_module_param_cb(char *param, char *val, | ||
| 48 | const char *modname); | ||
| 49 | |||
| 47 | struct device; | 50 | struct device; |
| 48 | 51 | ||
| 49 | extern __printf(3, 4) | 52 | extern __printf(3, 4) |
| @@ -94,11 +97,26 @@ do { \ | |||
| 94 | 97 | ||
| 95 | #else | 98 | #else |
| 96 | 99 | ||
| 100 | #include <linux/string.h> | ||
| 101 | #include <linux/errno.h> | ||
| 102 | |||
| 97 | static inline int ddebug_remove_module(const char *mod) | 103 | static inline int ddebug_remove_module(const char *mod) |
| 98 | { | 104 | { |
| 99 | return 0; | 105 | return 0; |
| 100 | } | 106 | } |
| 101 | 107 | ||
| 108 | static inline int ddebug_dyndbg_module_param_cb(char *param, char *val, | ||
| 109 | const char *modname) | ||
| 110 | { | ||
| 111 | if (strstr(param, "dyndbg")) { | ||
| 112 | /* avoid pr_warn(), which wants pr_fmt() fully defined */ | ||
| 113 | printk(KERN_WARNING "dyndbg param is supported only in " | ||
| 114 | "CONFIG_DYNAMIC_DEBUG builds\n"); | ||
| 115 | return 0; /* allow and ignore */ | ||
| 116 | } | ||
| 117 | return -EINVAL; | ||
| 118 | } | ||
| 119 | |||
| 102 | #define dynamic_pr_debug(fmt, ...) \ | 120 | #define dynamic_pr_debug(fmt, ...) \ |
| 103 | do { if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); } while (0) | 121 | do { if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); } while (0) |
| 104 | #define dynamic_dev_dbg(dev, fmt, ...) \ | 122 | #define dynamic_dev_dbg(dev, fmt, ...) \ |
diff --git a/include/linux/extcon.h b/include/linux/extcon.h new file mode 100644 index 000000000000..cdd401477656 --- /dev/null +++ b/include/linux/extcon.h | |||
| @@ -0,0 +1,324 @@ | |||
| 1 | /* | ||
| 2 | * External connector (extcon) class driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Samsung Electronics | ||
| 5 | * Author: Donggeun Kim <dg77.kim@samsung.com> | ||
| 6 | * Author: MyungJoo Ham <myungjoo.ham@samsung.com> | ||
| 7 | * | ||
| 8 | * based on switch class driver | ||
| 9 | * Copyright (C) 2008 Google, Inc. | ||
| 10 | * Author: Mike Lockwood <lockwood@android.com> | ||
| 11 | * | ||
| 12 | * This software is licensed under the terms of the GNU General Public | ||
| 13 | * License version 2, as published by the Free Software Foundation, and | ||
| 14 | * may be copied, distributed, and modified under those terms. | ||
| 15 | * | ||
| 16 | * This program is distributed in the hope that it will be useful, | ||
| 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 19 | * GNU General Public License for more details. | ||
| 20 | * | ||
| 21 | */ | ||
| 22 | |||
| 23 | #ifndef __LINUX_EXTCON_H__ | ||
| 24 | #define __LINUX_EXTCON_H__ | ||
| 25 | |||
| 26 | #include <linux/notifier.h> | ||
| 27 | |||
| 28 | #define SUPPORTED_CABLE_MAX 32 | ||
| 29 | #define CABLE_NAME_MAX 30 | ||
| 30 | |||
| 31 | /* | ||
| 32 | * The standard cable name is to help support general notifier | ||
| 33 | * and notifee device drivers to share the common names. | ||
| 34 | * Please use standard cable names unless your notifier device has | ||
| 35 | * a very unique and abnormal cable or | ||
| 36 | * the cable type is supposed to be used with only one unique | ||
| 37 | * pair of notifier/notifee devices. | ||
| 38 | * | ||
| 39 | * Please add any other "standard" cables used with extcon dev. | ||
| 40 | * | ||
| 41 | * You may add a dot and number to specify version or specification | ||
| 42 | * of the specific cable if it is required. (e.g., "Fast-charger.18" | ||
| 43 | * and "Fast-charger.10" for 1.8A and 1.0A chargers) | ||
| 44 | * However, the notifee and notifier should be able to handle such | ||
| 45 | * string and if the notifee can negotiate the protocol or idenify, | ||
| 46 | * you don't need such convention. This convention is helpful when | ||
| 47 | * notifier can distinguish but notifiee cannot. | ||
| 48 | */ | ||
| 49 | enum extcon_cable_name { | ||
| 50 | EXTCON_USB = 0, | ||
| 51 | EXTCON_USB_HOST, | ||
| 52 | EXTCON_TA, /* Travel Adaptor */ | ||
| 53 | EXTCON_FAST_CHARGER, | ||
| 54 | EXTCON_SLOW_CHARGER, | ||
| 55 | EXTCON_CHARGE_DOWNSTREAM, /* Charging an external device */ | ||
| 56 | EXTCON_HDMI, | ||
| 57 | EXTCON_MHL, | ||
| 58 | EXTCON_DVI, | ||
| 59 | EXTCON_VGA, | ||
| 60 | EXTCON_DOCK, | ||
| 61 | EXTCON_LINE_IN, | ||
| 62 | EXTCON_LINE_OUT, | ||
| 63 | EXTCON_MIC_IN, | ||
| 64 | EXTCON_HEADPHONE_OUT, | ||
| 65 | EXTCON_SPDIF_IN, | ||
| 66 | EXTCON_SPDIF_OUT, | ||
| 67 | EXTCON_VIDEO_IN, | ||
| 68 | EXTCON_VIDEO_OUT, | ||
| 69 | EXTCON_MECHANICAL, | ||
| 70 | }; | ||
| 71 | extern const char *extcon_cable_name[]; | ||
| 72 | |||
| 73 | struct extcon_cable; | ||
| 74 | |||
| 75 | /** | ||
| 76 | * struct extcon_dev - An extcon device represents one external connector. | ||
| 77 | * @name The name of this extcon device. Parent device name is used | ||
| 78 | * if NULL. | ||
| 79 | * @supported_cable Array of supported cable name ending with NULL. | ||
| 80 | * If supported_cable is NULL, cable name related APIs | ||
| 81 | * are disabled. | ||
| 82 | * @mutually_exclusive Array of mutually exclusive set of cables that cannot | ||
| 83 | * be attached simultaneously. The array should be | ||
| 84 | * ending with NULL or be NULL (no mutually exclusive | ||
| 85 | * cables). For example, if it is { 0x7, 0x30, 0}, then, | ||
| 86 | * {0, 1}, {0, 1, 2}, {0, 2}, {1, 2}, or {4, 5} cannot | ||
| 87 | * be attached simulataneously. {0x7, 0} is equivalent to | ||
| 88 | * {0x3, 0x6, 0x5, 0}. If it is {0xFFFFFFFF, 0}, there | ||
| 89 | * can be no simultaneous connections. | ||
| 90 | * @print_name An optional callback to override the method to print the | ||
| 91 | * name of the extcon device. | ||
| 92 | * @print_state An optional callback to override the method to print the | ||
| 93 | * status of the extcon device. | ||
| 94 | * @dev Device of this extcon. Do not provide at register-time. | ||
| 95 | * @state Attach/detach state of this extcon. Do not provide at | ||
| 96 | * register-time | ||
| 97 | * @nh Notifier for the state change events from this extcon | ||
| 98 | * @entry To support list of extcon devices so that uses can search | ||
| 99 | * for extcon devices based on the extcon name. | ||
| 100 | * @lock | ||
| 101 | * @max_supported Internal value to store the number of cables. | ||
| 102 | * @extcon_dev_type Device_type struct to provide attribute_groups | ||
| 103 | * customized for each extcon device. | ||
| 104 | * @cables Sysfs subdirectories. Each represents one cable. | ||
| 105 | * | ||
| 106 | * In most cases, users only need to provide "User initializing data" of | ||
| 107 | * this struct when registering an extcon. In some exceptional cases, | ||
| 108 | * optional callbacks may be needed. However, the values in "internal data" | ||
| 109 | * are overwritten by register function. | ||
| 110 | */ | ||
| 111 | struct extcon_dev { | ||
| 112 | /* --- Optional user initializing data --- */ | ||
| 113 | const char *name; | ||
| 114 | const char **supported_cable; | ||
| 115 | const u32 *mutually_exclusive; | ||
| 116 | |||
| 117 | /* --- Optional callbacks to override class functions --- */ | ||
| 118 | ssize_t (*print_name)(struct extcon_dev *edev, char *buf); | ||
| 119 | ssize_t (*print_state)(struct extcon_dev *edev, char *buf); | ||
| 120 | |||
| 121 | /* --- Internal data. Please do not set. --- */ | ||
| 122 | struct device *dev; | ||
| 123 | u32 state; | ||
| 124 | struct raw_notifier_head nh; | ||
| 125 | struct list_head entry; | ||
| 126 | spinlock_t lock; /* could be called by irq handler */ | ||
| 127 | int max_supported; | ||
| 128 | |||
| 129 | /* /sys/class/extcon/.../cable.n/... */ | ||
| 130 | struct device_type extcon_dev_type; | ||
| 131 | struct extcon_cable *cables; | ||
| 132 | /* /sys/class/extcon/.../mutually_exclusive/... */ | ||
| 133 | struct attribute_group attr_g_muex; | ||
| 134 | struct attribute **attrs_muex; | ||
| 135 | struct device_attribute *d_attrs_muex; | ||
| 136 | }; | ||
| 137 | |||
| 138 | /** | ||
| 139 | * struct extcon_cable - An internal data for each cable of extcon device. | ||
| 140 | * @edev The extcon device | ||
| 141 | * @cable_index Index of this cable in the edev | ||
| 142 | * @attr_g Attribute group for the cable | ||
| 143 | * @attr_name "name" sysfs entry | ||
| 144 | * @attr_state "state" sysfs entry | ||
| 145 | * @attrs Array pointing to attr_name and attr_state for attr_g | ||
| 146 | */ | ||
| 147 | struct extcon_cable { | ||
| 148 | struct extcon_dev *edev; | ||
| 149 | int cable_index; | ||
| 150 | |||
| 151 | struct attribute_group attr_g; | ||
| 152 | struct device_attribute attr_name; | ||
| 153 | struct device_attribute attr_state; | ||
| 154 | |||
| 155 | struct attribute *attrs[3]; /* to be fed to attr_g.attrs */ | ||
| 156 | }; | ||
| 157 | |||
| 158 | /** | ||
| 159 | * struct extcon_specific_cable_nb - An internal data for | ||
| 160 | * extcon_register_interest(). | ||
| 161 | * @internal_nb a notifier block bridging extcon notifier and cable notifier. | ||
| 162 | * @user_nb user provided notifier block for events from a specific cable. | ||
| 163 | * @cable_index the target cable. | ||
| 164 | * @edev the target extcon device. | ||
| 165 | * @previous_value the saved previous event value. | ||
| 166 | */ | ||
| 167 | struct extcon_specific_cable_nb { | ||
| 168 | struct notifier_block internal_nb; | ||
| 169 | struct notifier_block *user_nb; | ||
| 170 | int cable_index; | ||
| 171 | struct extcon_dev *edev; | ||
| 172 | unsigned long previous_value; | ||
| 173 | }; | ||
| 174 | |||
| 175 | #if IS_ENABLED(CONFIG_EXTCON) | ||
| 176 | |||
| 177 | /* | ||
| 178 | * Following APIs are for notifiers or configurations. | ||
| 179 | * Notifiers are the external port and connection devices. | ||
| 180 | */ | ||
| 181 | extern int extcon_dev_register(struct extcon_dev *edev, struct device *dev); | ||
| 182 | extern void extcon_dev_unregister(struct extcon_dev *edev); | ||
| 183 | extern struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name); | ||
| 184 | |||
| 185 | /* | ||
| 186 | * get/set/update_state access the 32b encoded state value, which represents | ||
| 187 | * states of all possible cables of the multistate port. For example, if one | ||
| 188 | * calls extcon_set_state(edev, 0x7), it may mean that all the three cables | ||
| 189 | * are attached to the port. | ||
| 190 | */ | ||
| 191 | static inline u32 extcon_get_state(struct extcon_dev *edev) | ||
| 192 | { | ||
| 193 | return edev->state; | ||
| 194 | } | ||
| 195 | |||
| 196 | extern int extcon_set_state(struct extcon_dev *edev, u32 state); | ||
| 197 | extern int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state); | ||
| 198 | |||
| 199 | /* | ||
| 200 | * get/set_cable_state access each bit of the 32b encoded state value. | ||
| 201 | * They are used to access the status of each cable based on the cable_name | ||
| 202 | * or cable_index, which is retrived by extcon_find_cable_index | ||
| 203 | */ | ||
| 204 | extern int extcon_find_cable_index(struct extcon_dev *sdev, | ||
| 205 | const char *cable_name); | ||
| 206 | extern int extcon_get_cable_state_(struct extcon_dev *edev, int cable_index); | ||
| 207 | extern int extcon_set_cable_state_(struct extcon_dev *edev, int cable_index, | ||
| 208 | bool cable_state); | ||
| 209 | |||
| 210 | extern int extcon_get_cable_state(struct extcon_dev *edev, | ||
| 211 | const char *cable_name); | ||
| 212 | extern int extcon_set_cable_state(struct extcon_dev *edev, | ||
| 213 | const char *cable_name, bool cable_state); | ||
| 214 | |||
| 215 | /* | ||
| 216 | * Following APIs are for notifiees (those who want to be notified) | ||
| 217 | * to register a callback for events from a specific cable of the extcon. | ||
| 218 | * Notifiees are the connected device drivers wanting to get notified by | ||
| 219 | * a specific external port of a connection device. | ||
| 220 | */ | ||
| 221 | extern int extcon_register_interest(struct extcon_specific_cable_nb *obj, | ||
| 222 | const char *extcon_name, | ||
| 223 | const char *cable_name, | ||
| 224 | struct notifier_block *nb); | ||
| 225 | extern int extcon_unregister_interest(struct extcon_specific_cable_nb *nb); | ||
| 226 | |||
| 227 | /* | ||
| 228 | * Following APIs are to monitor every action of a notifier. | ||
| 229 | * Registerer gets notified for every external port of a connection device. | ||
| 230 | * Probably this could be used to debug an action of notifier; however, | ||
| 231 | * we do not recommend to use this at normal 'notifiee' device drivers who | ||
| 232 | * want to be notified by a specific external port of the notifier. | ||
| 233 | */ | ||
| 234 | extern int extcon_register_notifier(struct extcon_dev *edev, | ||
| 235 | struct notifier_block *nb); | ||
| 236 | extern int extcon_unregister_notifier(struct extcon_dev *edev, | ||
| 237 | struct notifier_block *nb); | ||
| 238 | #else /* CONFIG_EXTCON */ | ||
| 239 | static inline int extcon_dev_register(struct extcon_dev *edev, | ||
| 240 | struct device *dev) | ||
| 241 | { | ||
| 242 | return 0; | ||
| 243 | } | ||
| 244 | |||
| 245 | static inline void extcon_dev_unregister(struct extcon_dev *edev) { } | ||
| 246 | |||
| 247 | static inline u32 extcon_get_state(struct extcon_dev *edev) | ||
| 248 | { | ||
| 249 | return 0; | ||
| 250 | } | ||
| 251 | |||
| 252 | static inline int extcon_set_state(struct extcon_dev *edev, u32 state) | ||
| 253 | { | ||
| 254 | return 0; | ||
| 255 | } | ||
| 256 | |||
| 257 | static inline int extcon_update_state(struct extcon_dev *edev, u32 mask, | ||
| 258 | u32 state) | ||
| 259 | { | ||
| 260 | return 0; | ||
| 261 | } | ||
| 262 | |||
| 263 | static inline int extcon_find_cable_index(struct extcon_dev *edev, | ||
| 264 | const char *cable_name) | ||
| 265 | { | ||
| 266 | return 0; | ||
| 267 | } | ||
| 268 | |||
| 269 | static inline int extcon_get_cable_state_(struct extcon_dev *edev, | ||
| 270 | int cable_index) | ||
| 271 | { | ||
| 272 | return 0; | ||
| 273 | } | ||
| 274 | |||
| 275 | static inline int extcon_set_cable_state_(struct extcon_dev *edev, | ||
| 276 | int cable_index, bool cable_state) | ||
| 277 | { | ||
| 278 | return 0; | ||
| 279 | } | ||
| 280 | |||
| 281 | static inline int extcon_get_cable_state(struct extcon_dev *edev, | ||
| 282 | const char *cable_name) | ||
| 283 | { | ||
| 284 | return 0; | ||
| 285 | } | ||
| 286 | |||
| 287 | static inline int extcon_set_cable_state(struct extcon_dev *edev, | ||
| 288 | const char *cable_name, int state) | ||
| 289 | { | ||
| 290 | return 0; | ||
| 291 | } | ||
| 292 | |||
| 293 | static inline struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name) | ||
| 294 | { | ||
| 295 | return NULL; | ||
| 296 | } | ||
| 297 | |||
| 298 | static inline int extcon_register_notifier(struct extcon_dev *edev, | ||
| 299 | struct notifier_block *nb) | ||
| 300 | { | ||
| 301 | return 0; | ||
| 302 | } | ||
| 303 | |||
| 304 | static inline int extcon_unregister_notifier(struct extcon_dev *edev, | ||
| 305 | struct notifier_block *nb) | ||
| 306 | { | ||
| 307 | return 0; | ||
| 308 | } | ||
| 309 | |||
| 310 | static inline int extcon_register_interest(struct extcon_specific_cable_nb *obj, | ||
| 311 | const char *extcon_name, | ||
| 312 | const char *cable_name, | ||
| 313 | struct notifier_block *nb) | ||
| 314 | { | ||
| 315 | return 0; | ||
| 316 | } | ||
| 317 | |||
| 318 | static inline int extcon_unregister_interest(struct extcon_specific_cable_nb | ||
| 319 | *obj) | ||
| 320 | { | ||
| 321 | return 0; | ||
| 322 | } | ||
| 323 | #endif /* CONFIG_EXTCON */ | ||
| 324 | #endif /* __LINUX_EXTCON_H__ */ | ||
diff --git a/include/linux/extcon/extcon_gpio.h b/include/linux/extcon/extcon_gpio.h new file mode 100644 index 000000000000..a2129b73dcb1 --- /dev/null +++ b/include/linux/extcon/extcon_gpio.h | |||
| @@ -0,0 +1,52 @@ | |||
| 1 | /* | ||
| 2 | * External connector (extcon) class generic GPIO driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Samsung Electronics | ||
| 5 | * Author: MyungJoo Ham <myungjoo.ham@samsung.com> | ||
| 6 | * | ||
| 7 | * based on switch class driver | ||
| 8 | * Copyright (C) 2008 Google, Inc. | ||
| 9 | * Author: Mike Lockwood <lockwood@android.com> | ||
| 10 | * | ||
| 11 | * This software is licensed under the terms of the GNU General Public | ||
| 12 | * License version 2, as published by the Free Software Foundation, and | ||
| 13 | * may be copied, distributed, and modified under those terms. | ||
| 14 | * | ||
| 15 | * This program is distributed in the hope that it will be useful, | ||
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | * GNU General Public License for more details. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | #ifndef __EXTCON_GPIO_H__ | ||
| 22 | #define __EXTCON_GPIO_H__ __FILE__ | ||
| 23 | |||
| 24 | #include <linux/extcon.h> | ||
| 25 | |||
| 26 | /** | ||
| 27 | * struct gpio_extcon_platform_data - A simple GPIO-controlled extcon device. | ||
| 28 | * @name The name of this GPIO extcon device. | ||
| 29 | * @gpio Corresponding GPIO. | ||
| 30 | * @debounce Debounce time for GPIO IRQ in ms. | ||
| 31 | * @irq_flags IRQ Flags (e.g., IRQF_TRIGGER_LOW). | ||
| 32 | * @state_on print_state is overriden with state_on if attached. If Null, | ||
| 33 | * default method of extcon class is used. | ||
| 34 | * @state_off print_state is overriden with state_on if dettached. If Null, | ||
| 35 | * default method of extcon class is used. | ||
| 36 | * | ||
| 37 | * Note that in order for state_on or state_off to be valid, both state_on | ||
| 38 | * and state_off should be not NULL. If at least one of them is NULL, | ||
| 39 | * the print_state is not overriden. | ||
| 40 | */ | ||
| 41 | struct gpio_extcon_platform_data { | ||
| 42 | const char *name; | ||
| 43 | unsigned gpio; | ||
| 44 | unsigned long debounce; | ||
| 45 | unsigned long irq_flags; | ||
| 46 | |||
| 47 | /* if NULL, "0" or "1" will be printed */ | ||
| 48 | const char *state_on; | ||
| 49 | const char *state_off; | ||
| 50 | }; | ||
| 51 | |||
| 52 | #endif /* __EXTCON_GPIO_H__ */ | ||
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 6af8738ae7e9..68ed7f7e1fc9 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h | |||
| @@ -1062,8 +1062,10 @@ struct hyperv_service_callback { | |||
| 1062 | void (*callback) (void *context); | 1062 | void (*callback) (void *context); |
| 1063 | }; | 1063 | }; |
| 1064 | 1064 | ||
| 1065 | #define MAX_SRV_VER 0x7ffffff | ||
| 1065 | extern void vmbus_prep_negotiate_resp(struct icmsg_hdr *, | 1066 | extern void vmbus_prep_negotiate_resp(struct icmsg_hdr *, |
| 1066 | struct icmsg_negotiate *, u8 *); | 1067 | struct icmsg_negotiate *, u8 *, int, |
| 1068 | int); | ||
| 1067 | 1069 | ||
| 1068 | int hv_kvp_init(struct hv_util_service *); | 1070 | int hv_kvp_init(struct hv_util_service *); |
| 1069 | void hv_kvp_deinit(void); | 1071 | void hv_kvp_deinit(void); |
diff --git a/include/linux/mfd/max8997.h b/include/linux/mfd/max8997.h index 28726dd540f2..b40c08cd30bc 100644 --- a/include/linux/mfd/max8997.h +++ b/include/linux/mfd/max8997.h | |||
| @@ -99,34 +99,11 @@ struct max8997_muic_reg_data { | |||
| 99 | 99 | ||
| 100 | /** | 100 | /** |
| 101 | * struct max8997_muic_platform_data | 101 | * struct max8997_muic_platform_data |
| 102 | * @usb_callback: callback function for USB | ||
| 103 | * inform callee of USB type (HOST or DEVICE) | ||
| 104 | * and attached state(true or false) | ||
| 105 | * @charger_callback: callback function for charger | ||
| 106 | * inform callee of charger_type | ||
| 107 | * and attached state(true or false) | ||
| 108 | * @deskdock_callback: callback function for desk dock | ||
| 109 | * inform callee of attached state(true or false) | ||
| 110 | * @cardock_callback: callback function for car dock | ||
| 111 | * inform callee of attached state(true or false) | ||
| 112 | * @mhl_callback: callback function for MHL (Mobile High-definition Link) | ||
| 113 | * inform callee of attached state(true or false) | ||
| 114 | * @uart_callback: callback function for JIG UART | ||
| 115 | * inform callee of attached state(true or false) | ||
| 116 | * @init_data: array of max8997_muic_reg_data | 102 | * @init_data: array of max8997_muic_reg_data |
| 117 | * used for initializing registers of MAX8997 MUIC device | 103 | * used for initializing registers of MAX8997 MUIC device |
| 118 | * @num_init_data: array size of init_data | 104 | * @num_init_data: array size of init_data |
| 119 | */ | 105 | */ |
| 120 | struct max8997_muic_platform_data { | 106 | struct max8997_muic_platform_data { |
| 121 | void (*usb_callback)(enum max8997_muic_usb_type usb_type, | ||
| 122 | bool attached); | ||
| 123 | void (*charger_callback)(bool attached, | ||
| 124 | enum max8997_muic_charger_type charger_type); | ||
| 125 | void (*deskdock_callback) (bool attached); | ||
| 126 | void (*cardock_callback) (bool attached); | ||
| 127 | void (*mhl_callback) (bool attached); | ||
| 128 | void (*uart_callback) (bool attached); | ||
| 129 | |||
| 130 | struct max8997_muic_reg_data *init_data; | 107 | struct max8997_muic_reg_data *init_data; |
| 131 | int num_init_data; | 108 | int num_init_data; |
| 132 | }; | 109 | }; |
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h index ea36486378d8..1b14d25162cb 100644 --- a/include/linux/moduleparam.h +++ b/include/linux/moduleparam.h | |||
| @@ -320,7 +320,8 @@ extern int parse_args(const char *name, | |||
| 320 | unsigned num, | 320 | unsigned num, |
| 321 | s16 level_min, | 321 | s16 level_min, |
| 322 | s16 level_max, | 322 | s16 level_max, |
| 323 | int (*unknown)(char *param, char *val)); | 323 | int (*unknown)(char *param, char *val, |
| 324 | const char *doing)); | ||
| 324 | 325 | ||
| 325 | /* Called by module remove. */ | 326 | /* Called by module remove. */ |
| 326 | #ifdef CONFIG_SYSFS | 327 | #ifdef CONFIG_SYSFS |
diff --git a/include/linux/platform_data/emif_plat.h b/include/linux/platform_data/emif_plat.h new file mode 100644 index 000000000000..03378ca84061 --- /dev/null +++ b/include/linux/platform_data/emif_plat.h | |||
| @@ -0,0 +1,128 @@ | |||
| 1 | /* | ||
| 2 | * Definitions for TI EMIF device platform data | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Texas Instruments, Inc. | ||
| 5 | * | ||
| 6 | * Aneesh V <aneesh@ti.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | #ifndef __EMIF_PLAT_H | ||
| 13 | #define __EMIF_PLAT_H | ||
| 14 | |||
| 15 | /* Low power modes - EMIF_PWR_MGMT_CTRL */ | ||
| 16 | #define EMIF_LP_MODE_DISABLE 0 | ||
| 17 | #define EMIF_LP_MODE_CLOCK_STOP 1 | ||
| 18 | #define EMIF_LP_MODE_SELF_REFRESH 2 | ||
| 19 | #define EMIF_LP_MODE_PWR_DN 4 | ||
| 20 | |||
| 21 | /* Hardware capabilities */ | ||
| 22 | #define EMIF_HW_CAPS_LL_INTERFACE 0x00000001 | ||
| 23 | |||
| 24 | /* | ||
| 25 | * EMIF IP Revisions | ||
| 26 | * EMIF4D - Used in OMAP4 | ||
| 27 | * EMIF4D5 - Used in OMAP5 | ||
| 28 | */ | ||
| 29 | #define EMIF_4D 1 | ||
| 30 | #define EMIF_4D5 2 | ||
| 31 | |||
| 32 | /* | ||
| 33 | * PHY types | ||
| 34 | * ATTILAPHY - Used in OMAP4 | ||
| 35 | * INTELLIPHY - Used in OMAP5 | ||
| 36 | */ | ||
| 37 | #define EMIF_PHY_TYPE_ATTILAPHY 1 | ||
| 38 | #define EMIF_PHY_TYPE_INTELLIPHY 2 | ||
| 39 | |||
| 40 | /* Custom config requests */ | ||
| 41 | #define EMIF_CUSTOM_CONFIG_LPMODE 0x00000001 | ||
| 42 | #define EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL 0x00000002 | ||
| 43 | |||
| 44 | #ifndef __ASSEMBLY__ | ||
| 45 | /** | ||
| 46 | * struct ddr_device_info - All information about the DDR device except AC | ||
| 47 | * timing parameters | ||
| 48 | * @type: Device type (LPDDR2-S4, LPDDR2-S2 etc) | ||
| 49 | * @density: Device density | ||
| 50 | * @io_width: Bus width | ||
| 51 | * @cs1_used: Whether there is a DDR device attached to the second | ||
| 52 | * chip-select(CS1) of this EMIF instance | ||
| 53 | * @cal_resistors_per_cs: Whether there is one calibration resistor per | ||
| 54 | * chip-select or whether it's a single one for both | ||
| 55 | * @manufacturer: Manufacturer name string | ||
| 56 | */ | ||
| 57 | struct ddr_device_info { | ||
| 58 | u32 type; | ||
| 59 | u32 density; | ||
| 60 | u32 io_width; | ||
| 61 | u32 cs1_used; | ||
| 62 | u32 cal_resistors_per_cs; | ||
| 63 | char manufacturer[10]; | ||
| 64 | }; | ||
| 65 | |||
| 66 | /** | ||
| 67 | * struct emif_custom_configs - Custom configuration parameters/policies | ||
| 68 | * passed from the platform layer | ||
| 69 | * @mask: Mask to indicate which configs are requested | ||
| 70 | * @lpmode: LPMODE to be used in PWR_MGMT_CTRL register | ||
| 71 | * @lpmode_timeout_performance: Timeout before LPMODE entry when higher | ||
| 72 | * performance is desired at the cost of power (typically | ||
| 73 | * at higher OPPs) | ||
| 74 | * @lpmode_timeout_power: Timeout before LPMODE entry when better power | ||
| 75 | * savings is desired and performance is not important | ||
| 76 | * (typically at lower loads indicated by lower OPPs) | ||
| 77 | * @lpmode_freq_threshold: The DDR frequency threshold to identify between | ||
| 78 | * the above two cases: | ||
| 79 | * timeout = (freq >= lpmode_freq_threshold) ? | ||
| 80 | * lpmode_timeout_performance : | ||
| 81 | * lpmode_timeout_power; | ||
| 82 | * @temp_alert_poll_interval_ms: LPDDR2 MR4 polling interval at nominal | ||
| 83 | * temperature(in milliseconds). When temperature is high | ||
| 84 | * polling is done 4 times as frequently. | ||
| 85 | */ | ||
| 86 | struct emif_custom_configs { | ||
| 87 | u32 mask; | ||
| 88 | u32 lpmode; | ||
| 89 | u32 lpmode_timeout_performance; | ||
| 90 | u32 lpmode_timeout_power; | ||
| 91 | u32 lpmode_freq_threshold; | ||
| 92 | u32 temp_alert_poll_interval_ms; | ||
| 93 | }; | ||
| 94 | |||
| 95 | /** | ||
| 96 | * struct emif_platform_data - Platform data passed on EMIF platform | ||
| 97 | * device creation. Used by the driver. | ||
| 98 | * @hw_caps: Hw capabilities of the EMIF IP in the respective SoC | ||
| 99 | * @device_info: Device info structure containing information such | ||
| 100 | * as type, bus width, density etc | ||
| 101 | * @timings: Timings information from device datasheet passed | ||
| 102 | * as an array of 'struct lpddr2_timings'. Can be NULL | ||
| 103 | * if if default timings are ok | ||
| 104 | * @timings_arr_size: Size of the timings array. Depends on the number | ||
| 105 | * of different frequencies for which timings data | ||
| 106 | * is provided | ||
| 107 | * @min_tck: Minimum value of some timing parameters in terms | ||
| 108 | * of number of cycles. Can be NULL if default values | ||
| 109 | * are ok | ||
| 110 | * @custom_configs: Custom configurations requested by SoC or board | ||
| 111 | * code and the data for them. Can be NULL if default | ||
| 112 | * configurations done by the driver are ok. See | ||
| 113 | * documentation for 'struct emif_custom_configs' for | ||
| 114 | * more details | ||
| 115 | */ | ||
| 116 | struct emif_platform_data { | ||
| 117 | u32 hw_caps; | ||
| 118 | struct ddr_device_info *device_info; | ||
| 119 | const struct lpddr2_timings *timings; | ||
| 120 | u32 timings_arr_size; | ||
| 121 | const struct lpddr2_min_tck *min_tck; | ||
| 122 | struct emif_custom_configs *custom_configs; | ||
| 123 | u32 ip_rev; | ||
| 124 | u32 phy_type; | ||
| 125 | }; | ||
| 126 | #endif /* __ASSEMBLY__ */ | ||
| 127 | |||
| 128 | #endif /* __LINUX_EMIF_H */ | ||
diff --git a/include/linux/printk.h b/include/linux/printk.h index 0525927f203f..1bec2f7a2d42 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h | |||
| @@ -95,8 +95,19 @@ extern int printk_needs_cpu(int cpu); | |||
| 95 | extern void printk_tick(void); | 95 | extern void printk_tick(void); |
| 96 | 96 | ||
| 97 | #ifdef CONFIG_PRINTK | 97 | #ifdef CONFIG_PRINTK |
| 98 | asmlinkage __printf(5, 0) | ||
| 99 | int vprintk_emit(int facility, int level, | ||
| 100 | const char *dict, size_t dictlen, | ||
| 101 | const char *fmt, va_list args); | ||
| 102 | |||
| 98 | asmlinkage __printf(1, 0) | 103 | asmlinkage __printf(1, 0) |
| 99 | int vprintk(const char *fmt, va_list args); | 104 | int vprintk(const char *fmt, va_list args); |
| 105 | |||
| 106 | asmlinkage __printf(5, 6) __cold | ||
| 107 | asmlinkage int printk_emit(int facility, int level, | ||
| 108 | const char *dict, size_t dictlen, | ||
| 109 | const char *fmt, ...); | ||
| 110 | |||
| 100 | asmlinkage __printf(1, 2) __cold | 111 | asmlinkage __printf(1, 2) __cold |
| 101 | int printk(const char *fmt, ...); | 112 | int printk(const char *fmt, ...); |
| 102 | 113 | ||
| @@ -289,6 +300,8 @@ extern void dump_stack(void) __cold; | |||
| 289 | no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) | 300 | no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) |
| 290 | #endif | 301 | #endif |
| 291 | 302 | ||
| 303 | extern const struct file_operations kmsg_fops; | ||
| 304 | |||
| 292 | enum { | 305 | enum { |
| 293 | DUMP_PREFIX_NONE, | 306 | DUMP_PREFIX_NONE, |
| 294 | DUMP_PREFIX_ADDRESS, | 307 | DUMP_PREFIX_ADDRESS, |
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 0010009b2f00..381f06db2fe5 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h | |||
| @@ -27,6 +27,7 @@ struct attribute { | |||
| 27 | const char *name; | 27 | const char *name; |
| 28 | umode_t mode; | 28 | umode_t mode; |
| 29 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 29 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
| 30 | bool ignore_lockdep:1; | ||
| 30 | struct lock_class_key *key; | 31 | struct lock_class_key *key; |
| 31 | struct lock_class_key skey; | 32 | struct lock_class_key skey; |
| 32 | #endif | 33 | #endif |
| @@ -80,6 +81,17 @@ struct attribute_group { | |||
| 80 | 81 | ||
| 81 | #define __ATTR_NULL { .attr = { .name = NULL } } | 82 | #define __ATTR_NULL { .attr = { .name = NULL } } |
| 82 | 83 | ||
| 84 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
| 85 | #define __ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store) { \ | ||
| 86 | .attr = {.name = __stringify(_name), .mode = _mode, \ | ||
| 87 | .ignore_lockdep = true }, \ | ||
| 88 | .show = _show, \ | ||
| 89 | .store = _store, \ | ||
| 90 | } | ||
| 91 | #else | ||
| 92 | #define __ATTR_IGNORE_LOCKDEP __ATTR | ||
| 93 | #endif | ||
| 94 | |||
| 83 | #define attr_name(_attr) (_attr).attr.name | 95 | #define attr_name(_attr) (_attr).attr.name |
| 84 | 96 | ||
| 85 | struct file; | 97 | struct file; |
diff --git a/include/memory/jedec_ddr.h b/include/memory/jedec_ddr.h new file mode 100644 index 000000000000..ddad0f870e5d --- /dev/null +++ b/include/memory/jedec_ddr.h | |||
| @@ -0,0 +1,175 @@ | |||
| 1 | /* | ||
| 2 | * Definitions for DDR memories based on JEDEC specs | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Texas Instruments, Inc. | ||
| 5 | * | ||
| 6 | * Aneesh V <aneesh@ti.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | #ifndef __LINUX_JEDEC_DDR_H | ||
| 13 | #define __LINUX_JEDEC_DDR_H | ||
| 14 | |||
| 15 | #include <linux/types.h> | ||
| 16 | |||
| 17 | /* DDR Densities */ | ||
| 18 | #define DDR_DENSITY_64Mb 1 | ||
| 19 | #define DDR_DENSITY_128Mb 2 | ||
| 20 | #define DDR_DENSITY_256Mb 3 | ||
| 21 | #define DDR_DENSITY_512Mb 4 | ||
| 22 | #define DDR_DENSITY_1Gb 5 | ||
| 23 | #define DDR_DENSITY_2Gb 6 | ||
| 24 | #define DDR_DENSITY_4Gb 7 | ||
| 25 | #define DDR_DENSITY_8Gb 8 | ||
| 26 | #define DDR_DENSITY_16Gb 9 | ||
| 27 | #define DDR_DENSITY_32Gb 10 | ||
| 28 | |||
| 29 | /* DDR type */ | ||
| 30 | #define DDR_TYPE_DDR2 1 | ||
| 31 | #define DDR_TYPE_DDR3 2 | ||
| 32 | #define DDR_TYPE_LPDDR2_S4 3 | ||
| 33 | #define DDR_TYPE_LPDDR2_S2 4 | ||
| 34 | #define DDR_TYPE_LPDDR2_NVM 5 | ||
| 35 | |||
| 36 | /* DDR IO width */ | ||
| 37 | #define DDR_IO_WIDTH_4 1 | ||
| 38 | #define DDR_IO_WIDTH_8 2 | ||
| 39 | #define DDR_IO_WIDTH_16 3 | ||
| 40 | #define DDR_IO_WIDTH_32 4 | ||
| 41 | |||
| 42 | /* Number of Row bits */ | ||
| 43 | #define R9 9 | ||
| 44 | #define R10 10 | ||
| 45 | #define R11 11 | ||
| 46 | #define R12 12 | ||
| 47 | #define R13 13 | ||
| 48 | #define R14 14 | ||
| 49 | #define R15 15 | ||
| 50 | #define R16 16 | ||
| 51 | |||
| 52 | /* Number of Column bits */ | ||
| 53 | #define C7 7 | ||
| 54 | #define C8 8 | ||
| 55 | #define C9 9 | ||
| 56 | #define C10 10 | ||
| 57 | #define C11 11 | ||
| 58 | #define C12 12 | ||
| 59 | |||
| 60 | /* Number of Banks */ | ||
| 61 | #define B1 0 | ||
| 62 | #define B2 1 | ||
| 63 | #define B4 2 | ||
| 64 | #define B8 3 | ||
| 65 | |||
| 66 | /* Refresh rate in nano-seconds */ | ||
| 67 | #define T_REFI_15_6 15600 | ||
| 68 | #define T_REFI_7_8 7800 | ||
| 69 | #define T_REFI_3_9 3900 | ||
| 70 | |||
| 71 | /* tRFC values */ | ||
| 72 | #define T_RFC_90 90000 | ||
| 73 | #define T_RFC_110 110000 | ||
| 74 | #define T_RFC_130 130000 | ||
| 75 | #define T_RFC_160 160000 | ||
| 76 | #define T_RFC_210 210000 | ||
| 77 | #define T_RFC_300 300000 | ||
| 78 | #define T_RFC_350 350000 | ||
| 79 | |||
| 80 | /* Mode register numbers */ | ||
| 81 | #define DDR_MR0 0 | ||
| 82 | #define DDR_MR1 1 | ||
| 83 | #define DDR_MR2 2 | ||
| 84 | #define DDR_MR3 3 | ||
| 85 | #define DDR_MR4 4 | ||
| 86 | #define DDR_MR5 5 | ||
| 87 | #define DDR_MR6 6 | ||
| 88 | #define DDR_MR7 7 | ||
| 89 | #define DDR_MR8 8 | ||
| 90 | #define DDR_MR9 9 | ||
| 91 | #define DDR_MR10 10 | ||
| 92 | #define DDR_MR11 11 | ||
| 93 | #define DDR_MR16 16 | ||
| 94 | #define DDR_MR17 17 | ||
| 95 | #define DDR_MR18 18 | ||
| 96 | |||
| 97 | /* | ||
| 98 | * LPDDR2 related defines | ||
| 99 | */ | ||
| 100 | |||
| 101 | /* MR4 register fields */ | ||
| 102 | #define MR4_SDRAM_REF_RATE_SHIFT 0 | ||
| 103 | #define MR4_SDRAM_REF_RATE_MASK 7 | ||
| 104 | #define MR4_TUF_SHIFT 7 | ||
| 105 | #define MR4_TUF_MASK (1 << 7) | ||
| 106 | |||
| 107 | /* MR4 SDRAM Refresh Rate field values */ | ||
| 108 | #define SDRAM_TEMP_NOMINAL 0x3 | ||
| 109 | #define SDRAM_TEMP_RESERVED_4 0x4 | ||
| 110 | #define SDRAM_TEMP_HIGH_DERATE_REFRESH 0x5 | ||
| 111 | #define SDRAM_TEMP_HIGH_DERATE_REFRESH_AND_TIMINGS 0x6 | ||
| 112 | #define SDRAM_TEMP_VERY_HIGH_SHUTDOWN 0x7 | ||
| 113 | |||
| 114 | #define NUM_DDR_ADDR_TABLE_ENTRIES 11 | ||
| 115 | #define NUM_DDR_TIMING_TABLE_ENTRIES 4 | ||
| 116 | |||
| 117 | /* Structure for DDR addressing info from the JEDEC spec */ | ||
| 118 | struct lpddr2_addressing { | ||
| 119 | u32 num_banks; | ||
| 120 | u32 tREFI_ns; | ||
| 121 | u32 tRFCab_ps; | ||
| 122 | }; | ||
| 123 | |||
| 124 | /* | ||
| 125 | * Structure for timings from the LPDDR2 datasheet | ||
| 126 | * All parameters are in pico seconds(ps) unless explicitly indicated | ||
| 127 | * with a suffix like tRAS_max_ns below | ||
| 128 | */ | ||
| 129 | struct lpddr2_timings { | ||
| 130 | u32 max_freq; | ||
| 131 | u32 min_freq; | ||
| 132 | u32 tRPab; | ||
| 133 | u32 tRCD; | ||
| 134 | u32 tWR; | ||
| 135 | u32 tRAS_min; | ||
| 136 | u32 tRRD; | ||
| 137 | u32 tWTR; | ||
| 138 | u32 tXP; | ||
| 139 | u32 tRTP; | ||
| 140 | u32 tCKESR; | ||
| 141 | u32 tDQSCK_max; | ||
| 142 | u32 tDQSCK_max_derated; | ||
| 143 | u32 tFAW; | ||
| 144 | u32 tZQCS; | ||
| 145 | u32 tZQCL; | ||
| 146 | u32 tZQinit; | ||
| 147 | u32 tRAS_max_ns; | ||
| 148 | }; | ||
| 149 | |||
| 150 | /* | ||
| 151 | * Min value for some parameters in terms of number of tCK cycles(nCK) | ||
| 152 | * Please set to zero parameters that are not valid for a given memory | ||
| 153 | * type | ||
| 154 | */ | ||
| 155 | struct lpddr2_min_tck { | ||
| 156 | u32 tRPab; | ||
| 157 | u32 tRCD; | ||
| 158 | u32 tWR; | ||
| 159 | u32 tRASmin; | ||
| 160 | u32 tRRD; | ||
| 161 | u32 tWTR; | ||
| 162 | u32 tXP; | ||
| 163 | u32 tRTP; | ||
| 164 | u32 tCKE; | ||
| 165 | u32 tCKESR; | ||
| 166 | u32 tFAW; | ||
| 167 | }; | ||
| 168 | |||
| 169 | extern const struct lpddr2_addressing | ||
| 170 | lpddr2_jedec_addressing_table[NUM_DDR_ADDR_TABLE_ENTRIES]; | ||
| 171 | extern const struct lpddr2_timings | ||
| 172 | lpddr2_jedec_timings[NUM_DDR_TIMING_TABLE_ENTRIES]; | ||
| 173 | extern const struct lpddr2_min_tck lpddr2_jedec_min_tck; | ||
| 174 | |||
| 175 | #endif /* __LINUX_JEDEC_DDR_H */ | ||
diff --git a/init/main.c b/init/main.c index cb54cd3dbf05..1ca6b32c4828 100644 --- a/init/main.c +++ b/init/main.c | |||
| @@ -226,7 +226,7 @@ static int __init loglevel(char *str) | |||
| 226 | early_param("loglevel", loglevel); | 226 | early_param("loglevel", loglevel); |
| 227 | 227 | ||
| 228 | /* Change NUL term back to "=", to make "param" the whole string. */ | 228 | /* Change NUL term back to "=", to make "param" the whole string. */ |
| 229 | static int __init repair_env_string(char *param, char *val) | 229 | static int __init repair_env_string(char *param, char *val, const char *unused) |
| 230 | { | 230 | { |
| 231 | if (val) { | 231 | if (val) { |
| 232 | /* param=val or param="val"? */ | 232 | /* param=val or param="val"? */ |
| @@ -246,9 +246,9 @@ static int __init repair_env_string(char *param, char *val) | |||
| 246 | * Unknown boot options get handed to init, unless they look like | 246 | * Unknown boot options get handed to init, unless they look like |
| 247 | * unused parameters (modprobe will find them in /proc/cmdline). | 247 | * unused parameters (modprobe will find them in /proc/cmdline). |
| 248 | */ | 248 | */ |
| 249 | static int __init unknown_bootoption(char *param, char *val) | 249 | static int __init unknown_bootoption(char *param, char *val, const char *unused) |
| 250 | { | 250 | { |
| 251 | repair_env_string(param, val); | 251 | repair_env_string(param, val, unused); |
| 252 | 252 | ||
| 253 | /* Handle obsolete-style parameters */ | 253 | /* Handle obsolete-style parameters */ |
| 254 | if (obsolete_checksetup(param)) | 254 | if (obsolete_checksetup(param)) |
| @@ -385,7 +385,7 @@ static noinline void __init_refok rest_init(void) | |||
| 385 | } | 385 | } |
| 386 | 386 | ||
| 387 | /* Check for early params. */ | 387 | /* Check for early params. */ |
| 388 | static int __init do_early_param(char *param, char *val) | 388 | static int __init do_early_param(char *param, char *val, const char *unused) |
| 389 | { | 389 | { |
| 390 | const struct obs_kernel_param *p; | 390 | const struct obs_kernel_param *p; |
| 391 | 391 | ||
| @@ -725,14 +725,14 @@ static initcall_t *initcall_levels[] __initdata = { | |||
| 725 | }; | 725 | }; |
| 726 | 726 | ||
| 727 | static char *initcall_level_names[] __initdata = { | 727 | static char *initcall_level_names[] __initdata = { |
| 728 | "early parameters", | 728 | "early", |
| 729 | "core parameters", | 729 | "core", |
| 730 | "postcore parameters", | 730 | "postcore", |
| 731 | "arch parameters", | 731 | "arch", |
| 732 | "subsys parameters", | 732 | "subsys", |
| 733 | "fs parameters", | 733 | "fs", |
| 734 | "device parameters", | 734 | "device", |
| 735 | "late parameters", | 735 | "late", |
| 736 | }; | 736 | }; |
| 737 | 737 | ||
| 738 | static void __init do_initcall_level(int level) | 738 | static void __init do_initcall_level(int level) |
| @@ -745,7 +745,7 @@ static void __init do_initcall_level(int level) | |||
| 745 | static_command_line, __start___param, | 745 | static_command_line, __start___param, |
| 746 | __stop___param - __start___param, | 746 | __stop___param - __start___param, |
| 747 | level, level, | 747 | level, level, |
| 748 | repair_env_string); | 748 | &repair_env_string); |
| 749 | 749 | ||
| 750 | for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++) | 750 | for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++) |
| 751 | do_one_initcall(*fn); | 751 | do_one_initcall(*fn); |
| @@ -755,8 +755,13 @@ static void __init do_initcalls(void) | |||
| 755 | { | 755 | { |
| 756 | int level; | 756 | int level; |
| 757 | 757 | ||
| 758 | for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++) | 758 | for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++) { |
| 759 | pr_info("initlevel:%d=%s, %d registered initcalls\n", | ||
| 760 | level, initcall_level_names[level], | ||
| 761 | (int) (initcall_levels[level+1] | ||
| 762 | - initcall_levels[level])); | ||
| 759 | do_initcall_level(level); | 763 | do_initcall_level(level); |
| 764 | } | ||
| 760 | } | 765 | } |
| 761 | 766 | ||
| 762 | /* | 767 | /* |
diff --git a/kernel/module.c b/kernel/module.c index 78ac6ec1e425..a4e60973ca73 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -2953,7 +2953,7 @@ static struct module *load_module(void __user *umod, | |||
| 2953 | 2953 | ||
| 2954 | /* Module is ready to execute: parsing args may do that. */ | 2954 | /* Module is ready to execute: parsing args may do that. */ |
| 2955 | err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, | 2955 | err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, |
| 2956 | -32768, 32767, NULL); | 2956 | -32768, 32767, &ddebug_dyndbg_module_param_cb); |
| 2957 | if (err < 0) | 2957 | if (err < 0) |
| 2958 | goto unlink; | 2958 | goto unlink; |
| 2959 | 2959 | ||
diff --git a/kernel/params.c b/kernel/params.c index f37d82631347..ed35345be536 100644 --- a/kernel/params.c +++ b/kernel/params.c | |||
| @@ -85,11 +85,13 @@ bool parameq(const char *a, const char *b) | |||
| 85 | 85 | ||
| 86 | static int parse_one(char *param, | 86 | static int parse_one(char *param, |
| 87 | char *val, | 87 | char *val, |
| 88 | const char *doing, | ||
| 88 | const struct kernel_param *params, | 89 | const struct kernel_param *params, |
| 89 | unsigned num_params, | 90 | unsigned num_params, |
| 90 | s16 min_level, | 91 | s16 min_level, |
| 91 | s16 max_level, | 92 | s16 max_level, |
| 92 | int (*handle_unknown)(char *param, char *val)) | 93 | int (*handle_unknown)(char *param, char *val, |
| 94 | const char *doing)) | ||
| 93 | { | 95 | { |
| 94 | unsigned int i; | 96 | unsigned int i; |
| 95 | int err; | 97 | int err; |
| @@ -104,8 +106,8 @@ static int parse_one(char *param, | |||
| 104 | if (!val && params[i].ops->set != param_set_bool | 106 | if (!val && params[i].ops->set != param_set_bool |
| 105 | && params[i].ops->set != param_set_bint) | 107 | && params[i].ops->set != param_set_bint) |
| 106 | return -EINVAL; | 108 | return -EINVAL; |
| 107 | pr_debug("They are equal! Calling %p\n", | 109 | pr_debug("handling %s with %p\n", param, |
| 108 | params[i].ops->set); | 110 | params[i].ops->set); |
| 109 | mutex_lock(¶m_lock); | 111 | mutex_lock(¶m_lock); |
| 110 | err = params[i].ops->set(val, ¶ms[i]); | 112 | err = params[i].ops->set(val, ¶ms[i]); |
| 111 | mutex_unlock(¶m_lock); | 113 | mutex_unlock(¶m_lock); |
| @@ -114,11 +116,11 @@ static int parse_one(char *param, | |||
| 114 | } | 116 | } |
| 115 | 117 | ||
| 116 | if (handle_unknown) { | 118 | if (handle_unknown) { |
| 117 | pr_debug("Unknown argument: calling %p\n", handle_unknown); | 119 | pr_debug("doing %s: %s='%s'\n", doing, param, val); |
| 118 | return handle_unknown(param, val); | 120 | return handle_unknown(param, val, doing); |
| 119 | } | 121 | } |
| 120 | 122 | ||
| 121 | pr_debug("Unknown argument `%s'\n", param); | 123 | pr_debug("Unknown argument '%s'\n", param); |
| 122 | return -ENOENT; | 124 | return -ENOENT; |
| 123 | } | 125 | } |
| 124 | 126 | ||
| @@ -175,49 +177,47 @@ static char *next_arg(char *args, char **param, char **val) | |||
| 175 | } | 177 | } |
| 176 | 178 | ||
| 177 | /* Args looks like "foo=bar,bar2 baz=fuz wiz". */ | 179 | /* Args looks like "foo=bar,bar2 baz=fuz wiz". */ |
| 178 | int parse_args(const char *name, | 180 | int parse_args(const char *doing, |
| 179 | char *args, | 181 | char *args, |
| 180 | const struct kernel_param *params, | 182 | const struct kernel_param *params, |
| 181 | unsigned num, | 183 | unsigned num, |
| 182 | s16 min_level, | 184 | s16 min_level, |
| 183 | s16 max_level, | 185 | s16 max_level, |
| 184 | int (*unknown)(char *param, char *val)) | 186 | int (*unknown)(char *param, char *val, const char *doing)) |
| 185 | { | 187 | { |
| 186 | char *param, *val; | 188 | char *param, *val; |
| 187 | 189 | ||
| 188 | pr_debug("Parsing ARGS: %s\n", args); | ||
| 189 | |||
| 190 | /* Chew leading spaces */ | 190 | /* Chew leading spaces */ |
| 191 | args = skip_spaces(args); | 191 | args = skip_spaces(args); |
| 192 | 192 | ||
| 193 | if (*args) | ||
| 194 | pr_debug("doing %s, parsing ARGS: '%s'\n", doing, args); | ||
| 195 | |||
| 193 | while (*args) { | 196 | while (*args) { |
| 194 | int ret; | 197 | int ret; |
| 195 | int irq_was_disabled; | 198 | int irq_was_disabled; |
| 196 | 199 | ||
| 197 | args = next_arg(args, ¶m, &val); | 200 | args = next_arg(args, ¶m, &val); |
| 198 | irq_was_disabled = irqs_disabled(); | 201 | irq_was_disabled = irqs_disabled(); |
| 199 | ret = parse_one(param, val, params, num, | 202 | ret = parse_one(param, val, doing, params, num, |
| 200 | min_level, max_level, unknown); | 203 | min_level, max_level, unknown); |
| 201 | if (irq_was_disabled && !irqs_disabled()) { | 204 | if (irq_was_disabled && !irqs_disabled()) |
| 202 | printk(KERN_WARNING "parse_args(): option '%s' enabled " | 205 | pr_warn("%s: option '%s' enabled irq's!\n", |
| 203 | "irq's!\n", param); | 206 | doing, param); |
| 204 | } | 207 | |
| 205 | switch (ret) { | 208 | switch (ret) { |
| 206 | case -ENOENT: | 209 | case -ENOENT: |
| 207 | printk(KERN_ERR "%s: Unknown parameter `%s'\n", | 210 | pr_err("%s: Unknown parameter `%s'\n", doing, param); |
| 208 | name, param); | ||
| 209 | return ret; | 211 | return ret; |
| 210 | case -ENOSPC: | 212 | case -ENOSPC: |
| 211 | printk(KERN_ERR | 213 | pr_err("%s: `%s' too large for parameter `%s'\n", |
| 212 | "%s: `%s' too large for parameter `%s'\n", | 214 | doing, val ?: "", param); |
| 213 | name, val ?: "", param); | ||
| 214 | return ret; | 215 | return ret; |
| 215 | case 0: | 216 | case 0: |
| 216 | break; | 217 | break; |
| 217 | default: | 218 | default: |
| 218 | printk(KERN_ERR | 219 | pr_err("%s: `%s' invalid for parameter `%s'\n", |
| 219 | "%s: `%s' invalid for parameter `%s'\n", | 220 | doing, val ?: "", param); |
| 220 | name, val ?: "", param); | ||
| 221 | return ret; | 221 | return ret; |
| 222 | } | 222 | } |
| 223 | } | 223 | } |
| @@ -263,8 +263,7 @@ STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", unsigned long, strict_strtoul); | |||
| 263 | int param_set_charp(const char *val, const struct kernel_param *kp) | 263 | int param_set_charp(const char *val, const struct kernel_param *kp) |
| 264 | { | 264 | { |
| 265 | if (strlen(val) > 1024) { | 265 | if (strlen(val) > 1024) { |
| 266 | printk(KERN_ERR "%s: string parameter too long\n", | 266 | pr_err("%s: string parameter too long\n", kp->name); |
| 267 | kp->name); | ||
| 268 | return -ENOSPC; | 267 | return -ENOSPC; |
| 269 | } | 268 | } |
| 270 | 269 | ||
| @@ -400,8 +399,7 @@ static int param_array(const char *name, | |||
| 400 | int len; | 399 | int len; |
| 401 | 400 | ||
| 402 | if (*num == max) { | 401 | if (*num == max) { |
| 403 | printk(KERN_ERR "%s: can only take %i arguments\n", | 402 | pr_err("%s: can only take %i arguments\n", name, max); |
| 404 | name, max); | ||
| 405 | return -EINVAL; | 403 | return -EINVAL; |
| 406 | } | 404 | } |
| 407 | len = strcspn(val, ","); | 405 | len = strcspn(val, ","); |
| @@ -420,8 +418,7 @@ static int param_array(const char *name, | |||
| 420 | } while (save == ','); | 418 | } while (save == ','); |
| 421 | 419 | ||
| 422 | if (*num < min) { | 420 | if (*num < min) { |
| 423 | printk(KERN_ERR "%s: needs at least %i arguments\n", | 421 | pr_err("%s: needs at least %i arguments\n", name, min); |
| 424 | name, min); | ||
| 425 | return -EINVAL; | 422 | return -EINVAL; |
| 426 | } | 423 | } |
| 427 | return 0; | 424 | return 0; |
| @@ -480,7 +477,7 @@ int param_set_copystring(const char *val, const struct kernel_param *kp) | |||
| 480 | const struct kparam_string *kps = kp->str; | 477 | const struct kparam_string *kps = kp->str; |
| 481 | 478 | ||
| 482 | if (strlen(val)+1 > kps->maxlen) { | 479 | if (strlen(val)+1 > kps->maxlen) { |
| 483 | printk(KERN_ERR "%s: string doesn't fit in %u chars.\n", | 480 | pr_err("%s: string doesn't fit in %u chars.\n", |
| 484 | kp->name, kps->maxlen-1); | 481 | kp->name, kps->maxlen-1); |
| 485 | return -ENOSPC; | 482 | return -ENOSPC; |
| 486 | } | 483 | } |
| @@ -750,11 +747,8 @@ static struct module_kobject * __init locate_module_kobject(const char *name) | |||
| 750 | #endif | 747 | #endif |
| 751 | if (err) { | 748 | if (err) { |
| 752 | kobject_put(&mk->kobj); | 749 | kobject_put(&mk->kobj); |
| 753 | printk(KERN_ERR | 750 | pr_crit("Adding module '%s' to sysfs failed (%d), the system may be unstable.\n", |
| 754 | "Module '%s' failed add to sysfs, error number %d\n", | ||
| 755 | name, err); | 751 | name, err); |
| 756 | printk(KERN_ERR | ||
| 757 | "The system will be unstable now.\n"); | ||
| 758 | return NULL; | 752 | return NULL; |
| 759 | } | 753 | } |
| 760 | 754 | ||
diff --git a/kernel/printk.c b/kernel/printk.c index b663c2c95d39..32462d2b364a 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
| @@ -41,6 +41,7 @@ | |||
| 41 | #include <linux/cpu.h> | 41 | #include <linux/cpu.h> |
| 42 | #include <linux/notifier.h> | 42 | #include <linux/notifier.h> |
| 43 | #include <linux/rculist.h> | 43 | #include <linux/rculist.h> |
| 44 | #include <linux/poll.h> | ||
| 44 | 45 | ||
| 45 | #include <asm/uaccess.h> | 46 | #include <asm/uaccess.h> |
| 46 | 47 | ||
| @@ -54,8 +55,6 @@ void asmlinkage __attribute__((weak)) early_printk(const char *fmt, ...) | |||
| 54 | { | 55 | { |
| 55 | } | 56 | } |
| 56 | 57 | ||
| 57 | #define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT) | ||
| 58 | |||
| 59 | /* printk's without a loglevel use this.. */ | 58 | /* printk's without a loglevel use this.. */ |
| 60 | #define DEFAULT_MESSAGE_LOGLEVEL CONFIG_DEFAULT_MESSAGE_LOGLEVEL | 59 | #define DEFAULT_MESSAGE_LOGLEVEL CONFIG_DEFAULT_MESSAGE_LOGLEVEL |
| 61 | 60 | ||
| @@ -99,24 +98,6 @@ EXPORT_SYMBOL_GPL(console_drivers); | |||
| 99 | static int console_locked, console_suspended; | 98 | static int console_locked, console_suspended; |
| 100 | 99 | ||
| 101 | /* | 100 | /* |
| 102 | * logbuf_lock protects log_buf, log_start, log_end, con_start and logged_chars | ||
| 103 | * It is also used in interesting ways to provide interlocking in | ||
| 104 | * console_unlock();. | ||
| 105 | */ | ||
| 106 | static DEFINE_RAW_SPINLOCK(logbuf_lock); | ||
| 107 | |||
| 108 | #define LOG_BUF_MASK (log_buf_len-1) | ||
| 109 | #define LOG_BUF(idx) (log_buf[(idx) & LOG_BUF_MASK]) | ||
| 110 | |||
| 111 | /* | ||
| 112 | * The indices into log_buf are not constrained to log_buf_len - they | ||
| 113 | * must be masked before subscripting | ||
| 114 | */ | ||
| 115 | static unsigned log_start; /* Index into log_buf: next char to be read by syslog() */ | ||
| 116 | static unsigned con_start; /* Index into log_buf: next char to be sent to consoles */ | ||
| 117 | static unsigned log_end; /* Index into log_buf: most-recently-written-char + 1 */ | ||
| 118 | |||
| 119 | /* | ||
| 120 | * If exclusive_console is non-NULL then only this console is to be printed to. | 101 | * If exclusive_console is non-NULL then only this console is to be printed to. |
| 121 | */ | 102 | */ |
| 122 | static struct console *exclusive_console; | 103 | static struct console *exclusive_console; |
| @@ -145,13 +126,491 @@ EXPORT_SYMBOL(console_set_on_cmdline); | |||
| 145 | /* Flag: console code may call schedule() */ | 126 | /* Flag: console code may call schedule() */ |
| 146 | static int console_may_schedule; | 127 | static int console_may_schedule; |
| 147 | 128 | ||
| 129 | /* | ||
| 130 | * The printk log buffer consists of a chain of concatenated variable | ||
| 131 | * length records. Every record starts with a record header, containing | ||
| 132 | * the overall length of the record. | ||
| 133 | * | ||
| 134 | * The heads to the first and last entry in the buffer, as well as the | ||
| 135 | * sequence numbers of these both entries are maintained when messages | ||
| 136 | * are stored.. | ||
| 137 | * | ||
| 138 | * If the heads indicate available messages, the length in the header | ||
| 139 | * tells the start next message. A length == 0 for the next message | ||
| 140 | * indicates a wrap-around to the beginning of the buffer. | ||
| 141 | * | ||
| 142 | * Every record carries the monotonic timestamp in microseconds, as well as | ||
| 143 | * the standard userspace syslog level and syslog facility. The usual | ||
| 144 | * kernel messages use LOG_KERN; userspace-injected messages always carry | ||
| 145 | * a matching syslog facility, by default LOG_USER. The origin of every | ||
| 146 | * message can be reliably determined that way. | ||
| 147 | * | ||
| 148 | * The human readable log message directly follows the message header. The | ||
| 149 | * length of the message text is stored in the header, the stored message | ||
| 150 | * is not terminated. | ||
| 151 | * | ||
| 152 | * Optionally, a message can carry a dictionary of properties (key/value pairs), | ||
| 153 | * to provide userspace with a machine-readable message context. | ||
| 154 | * | ||
| 155 | * Examples for well-defined, commonly used property names are: | ||
| 156 | * DEVICE=b12:8 device identifier | ||
| 157 | * b12:8 block dev_t | ||
| 158 | * c127:3 char dev_t | ||
| 159 | * n8 netdev ifindex | ||
| 160 | * +sound:card0 subsystem:devname | ||
| 161 | * SUBSYSTEM=pci driver-core subsystem name | ||
| 162 | * | ||
| 163 | * Valid characters in property names are [a-zA-Z0-9.-_]. The plain text value | ||
| 164 | * follows directly after a '=' character. Every property is terminated by | ||
| 165 | * a '\0' character. The last property is not terminated. | ||
| 166 | * | ||
| 167 | * Example of a message structure: | ||
| 168 | * 0000 ff 8f 00 00 00 00 00 00 monotonic time in nsec | ||
| 169 | * 0008 34 00 record is 52 bytes long | ||
| 170 | * 000a 0b 00 text is 11 bytes long | ||
| 171 | * 000c 1f 00 dictionary is 23 bytes long | ||
| 172 | * 000e 03 00 LOG_KERN (facility) LOG_ERR (level) | ||
| 173 | * 0010 69 74 27 73 20 61 20 6c "it's a l" | ||
| 174 | * 69 6e 65 "ine" | ||
| 175 | * 001b 44 45 56 49 43 "DEVIC" | ||
| 176 | * 45 3d 62 38 3a 32 00 44 "E=b8:2\0D" | ||
| 177 | * 52 49 56 45 52 3d 62 75 "RIVER=bu" | ||
| 178 | * 67 "g" | ||
| 179 | * 0032 00 00 00 padding to next message header | ||
| 180 | * | ||
| 181 | * The 'struct log' buffer header must never be directly exported to | ||
| 182 | * userspace, it is a kernel-private implementation detail that might | ||
| 183 | * need to be changed in the future, when the requirements change. | ||
| 184 | * | ||
| 185 | * /dev/kmsg exports the structured data in the following line format: | ||
| 186 | * "level,sequnum,timestamp;<message text>\n" | ||
| 187 | * | ||
| 188 | * The optional key/value pairs are attached as continuation lines starting | ||
| 189 | * with a space character and terminated by a newline. All possible | ||
| 190 | * non-prinatable characters are escaped in the "\xff" notation. | ||
| 191 | * | ||
| 192 | * Users of the export format should ignore possible additional values | ||
| 193 | * separated by ',', and find the message after the ';' character. | ||
| 194 | */ | ||
| 195 | |||
| 196 | struct log { | ||
| 197 | u64 ts_nsec; /* timestamp in nanoseconds */ | ||
| 198 | u16 len; /* length of entire record */ | ||
| 199 | u16 text_len; /* length of text buffer */ | ||
| 200 | u16 dict_len; /* length of dictionary buffer */ | ||
| 201 | u16 level; /* syslog level + facility */ | ||
| 202 | }; | ||
| 203 | |||
| 204 | /* | ||
| 205 | * The logbuf_lock protects kmsg buffer, indices, counters. It is also | ||
| 206 | * used in interesting ways to provide interlocking in console_unlock(); | ||
| 207 | */ | ||
| 208 | static DEFINE_RAW_SPINLOCK(logbuf_lock); | ||
| 209 | |||
| 210 | /* the next printk record to read by syslog(READ) or /proc/kmsg */ | ||
| 211 | static u64 syslog_seq; | ||
| 212 | static u32 syslog_idx; | ||
| 213 | |||
| 214 | /* index and sequence number of the first record stored in the buffer */ | ||
| 215 | static u64 log_first_seq; | ||
| 216 | static u32 log_first_idx; | ||
| 217 | |||
| 218 | /* index and sequence number of the next record to store in the buffer */ | ||
| 219 | static u64 log_next_seq; | ||
| 148 | #ifdef CONFIG_PRINTK | 220 | #ifdef CONFIG_PRINTK |
| 221 | static u32 log_next_idx; | ||
| 222 | |||
| 223 | /* the next printk record to read after the last 'clear' command */ | ||
| 224 | static u64 clear_seq; | ||
| 225 | static u32 clear_idx; | ||
| 226 | |||
| 227 | #define LOG_LINE_MAX 1024 | ||
| 149 | 228 | ||
| 150 | static char __log_buf[__LOG_BUF_LEN]; | 229 | /* record buffer */ |
| 230 | #if !defined(CONFIG_64BIT) || defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) | ||
| 231 | #define LOG_ALIGN 4 | ||
| 232 | #else | ||
| 233 | #define LOG_ALIGN 8 | ||
| 234 | #endif | ||
| 235 | #define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT) | ||
| 236 | static char __log_buf[__LOG_BUF_LEN] __aligned(LOG_ALIGN); | ||
| 151 | static char *log_buf = __log_buf; | 237 | static char *log_buf = __log_buf; |
| 152 | static int log_buf_len = __LOG_BUF_LEN; | 238 | static u32 log_buf_len = __LOG_BUF_LEN; |
| 153 | static unsigned logged_chars; /* Number of chars produced since last read+clear operation */ | 239 | |
| 154 | static int saved_console_loglevel = -1; | 240 | /* cpu currently holding logbuf_lock */ |
| 241 | static volatile unsigned int logbuf_cpu = UINT_MAX; | ||
| 242 | |||
| 243 | /* human readable text of the record */ | ||
| 244 | static char *log_text(const struct log *msg) | ||
| 245 | { | ||
| 246 | return (char *)msg + sizeof(struct log); | ||
| 247 | } | ||
| 248 | |||
| 249 | /* optional key/value pair dictionary attached to the record */ | ||
| 250 | static char *log_dict(const struct log *msg) | ||
| 251 | { | ||
| 252 | return (char *)msg + sizeof(struct log) + msg->text_len; | ||
| 253 | } | ||
| 254 | |||
| 255 | /* get record by index; idx must point to valid msg */ | ||
| 256 | static struct log *log_from_idx(u32 idx) | ||
| 257 | { | ||
| 258 | struct log *msg = (struct log *)(log_buf + idx); | ||
| 259 | |||
| 260 | /* | ||
| 261 | * A length == 0 record is the end of buffer marker. Wrap around and | ||
| 262 | * read the message at the start of the buffer. | ||
| 263 | */ | ||
| 264 | if (!msg->len) | ||
| 265 | return (struct log *)log_buf; | ||
| 266 | return msg; | ||
| 267 | } | ||
| 268 | |||
| 269 | /* get next record; idx must point to valid msg */ | ||
| 270 | static u32 log_next(u32 idx) | ||
| 271 | { | ||
| 272 | struct log *msg = (struct log *)(log_buf + idx); | ||
| 273 | |||
| 274 | /* length == 0 indicates the end of the buffer; wrap */ | ||
| 275 | /* | ||
| 276 | * A length == 0 record is the end of buffer marker. Wrap around and | ||
| 277 | * read the message at the start of the buffer as *this* one, and | ||
| 278 | * return the one after that. | ||
| 279 | */ | ||
| 280 | if (!msg->len) { | ||
| 281 | msg = (struct log *)log_buf; | ||
| 282 | return msg->len; | ||
| 283 | } | ||
| 284 | return idx + msg->len; | ||
| 285 | } | ||
| 286 | |||
| 287 | /* insert record into the buffer, discard old ones, update heads */ | ||
| 288 | static void log_store(int facility, int level, | ||
| 289 | const char *dict, u16 dict_len, | ||
| 290 | const char *text, u16 text_len) | ||
| 291 | { | ||
| 292 | struct log *msg; | ||
| 293 | u32 size, pad_len; | ||
| 294 | |||
| 295 | /* number of '\0' padding bytes to next message */ | ||
| 296 | size = sizeof(struct log) + text_len + dict_len; | ||
| 297 | pad_len = (-size) & (LOG_ALIGN - 1); | ||
| 298 | size += pad_len; | ||
| 299 | |||
| 300 | while (log_first_seq < log_next_seq) { | ||
| 301 | u32 free; | ||
| 302 | |||
| 303 | if (log_next_idx > log_first_idx) | ||
| 304 | free = max(log_buf_len - log_next_idx, log_first_idx); | ||
| 305 | else | ||
| 306 | free = log_first_idx - log_next_idx; | ||
| 307 | |||
| 308 | if (free > size + sizeof(struct log)) | ||
| 309 | break; | ||
| 310 | |||
| 311 | /* drop old messages until we have enough contiuous space */ | ||
| 312 | log_first_idx = log_next(log_first_idx); | ||
| 313 | log_first_seq++; | ||
| 314 | } | ||
| 315 | |||
| 316 | if (log_next_idx + size + sizeof(struct log) >= log_buf_len) { | ||
| 317 | /* | ||
| 318 | * This message + an additional empty header does not fit | ||
| 319 | * at the end of the buffer. Add an empty header with len == 0 | ||
| 320 | * to signify a wrap around. | ||
| 321 | */ | ||
| 322 | memset(log_buf + log_next_idx, 0, sizeof(struct log)); | ||
| 323 | log_next_idx = 0; | ||
| 324 | } | ||
| 325 | |||
| 326 | /* fill message */ | ||
| 327 | msg = (struct log *)(log_buf + log_next_idx); | ||
| 328 | memcpy(log_text(msg), text, text_len); | ||
| 329 | msg->text_len = text_len; | ||
| 330 | memcpy(log_dict(msg), dict, dict_len); | ||
| 331 | msg->dict_len = dict_len; | ||
| 332 | msg->level = (facility << 3) | (level & 7); | ||
| 333 | msg->ts_nsec = local_clock(); | ||
| 334 | memset(log_dict(msg) + dict_len, 0, pad_len); | ||
| 335 | msg->len = sizeof(struct log) + text_len + dict_len + pad_len; | ||
| 336 | |||
| 337 | /* insert message */ | ||
| 338 | log_next_idx += msg->len; | ||
| 339 | log_next_seq++; | ||
| 340 | } | ||
| 341 | |||
| 342 | /* /dev/kmsg - userspace message inject/listen interface */ | ||
| 343 | struct devkmsg_user { | ||
| 344 | u64 seq; | ||
| 345 | u32 idx; | ||
| 346 | struct mutex lock; | ||
| 347 | char buf[8192]; | ||
| 348 | }; | ||
| 349 | |||
| 350 | static ssize_t devkmsg_writev(struct kiocb *iocb, const struct iovec *iv, | ||
| 351 | unsigned long count, loff_t pos) | ||
| 352 | { | ||
| 353 | char *buf, *line; | ||
| 354 | int i; | ||
| 355 | int level = default_message_loglevel; | ||
| 356 | int facility = 1; /* LOG_USER */ | ||
| 357 | size_t len = iov_length(iv, count); | ||
| 358 | ssize_t ret = len; | ||
| 359 | |||
| 360 | if (len > LOG_LINE_MAX) | ||
| 361 | return -EINVAL; | ||
| 362 | buf = kmalloc(len+1, GFP_KERNEL); | ||
| 363 | if (buf == NULL) | ||
| 364 | return -ENOMEM; | ||
| 365 | |||
| 366 | line = buf; | ||
| 367 | for (i = 0; i < count; i++) { | ||
| 368 | if (copy_from_user(line, iv[i].iov_base, iv[i].iov_len)) | ||
| 369 | goto out; | ||
| 370 | line += iv[i].iov_len; | ||
| 371 | } | ||
| 372 | |||
| 373 | /* | ||
| 374 | * Extract and skip the syslog prefix <[0-9]*>. Coming from userspace | ||
| 375 | * the decimal value represents 32bit, the lower 3 bit are the log | ||
| 376 | * level, the rest are the log facility. | ||
| 377 | * | ||
| 378 | * If no prefix or no userspace facility is specified, we | ||
| 379 | * enforce LOG_USER, to be able to reliably distinguish | ||
| 380 | * kernel-generated messages from userspace-injected ones. | ||
| 381 | */ | ||
| 382 | line = buf; | ||
| 383 | if (line[0] == '<') { | ||
| 384 | char *endp = NULL; | ||
| 385 | |||
| 386 | i = simple_strtoul(line+1, &endp, 10); | ||
| 387 | if (endp && endp[0] == '>') { | ||
| 388 | level = i & 7; | ||
| 389 | if (i >> 3) | ||
| 390 | facility = i >> 3; | ||
| 391 | endp++; | ||
| 392 | len -= endp - line; | ||
| 393 | line = endp; | ||
| 394 | } | ||
| 395 | } | ||
| 396 | line[len] = '\0'; | ||
| 397 | |||
| 398 | printk_emit(facility, level, NULL, 0, "%s", line); | ||
| 399 | out: | ||
| 400 | kfree(buf); | ||
| 401 | return ret; | ||
| 402 | } | ||
| 403 | |||
| 404 | static ssize_t devkmsg_read(struct file *file, char __user *buf, | ||
| 405 | size_t count, loff_t *ppos) | ||
| 406 | { | ||
| 407 | struct devkmsg_user *user = file->private_data; | ||
| 408 | struct log *msg; | ||
| 409 | u64 ts_usec; | ||
| 410 | size_t i; | ||
| 411 | size_t len; | ||
| 412 | ssize_t ret; | ||
| 413 | |||
| 414 | if (!user) | ||
| 415 | return -EBADF; | ||
| 416 | |||
| 417 | mutex_lock(&user->lock); | ||
| 418 | raw_spin_lock(&logbuf_lock); | ||
| 419 | while (user->seq == log_next_seq) { | ||
| 420 | if (file->f_flags & O_NONBLOCK) { | ||
| 421 | ret = -EAGAIN; | ||
| 422 | raw_spin_unlock(&logbuf_lock); | ||
| 423 | goto out; | ||
| 424 | } | ||
| 425 | |||
| 426 | raw_spin_unlock(&logbuf_lock); | ||
| 427 | ret = wait_event_interruptible(log_wait, | ||
| 428 | user->seq != log_next_seq); | ||
| 429 | if (ret) | ||
| 430 | goto out; | ||
| 431 | raw_spin_lock(&logbuf_lock); | ||
| 432 | } | ||
| 433 | |||
| 434 | if (user->seq < log_first_seq) { | ||
| 435 | /* our last seen message is gone, return error and reset */ | ||
| 436 | user->idx = log_first_idx; | ||
| 437 | user->seq = log_first_seq; | ||
| 438 | ret = -EPIPE; | ||
| 439 | raw_spin_unlock(&logbuf_lock); | ||
| 440 | goto out; | ||
| 441 | } | ||
| 442 | |||
| 443 | msg = log_from_idx(user->idx); | ||
| 444 | ts_usec = msg->ts_nsec; | ||
| 445 | do_div(ts_usec, 1000); | ||
| 446 | len = sprintf(user->buf, "%u,%llu,%llu;", | ||
| 447 | msg->level, user->seq, ts_usec); | ||
| 448 | |||
| 449 | /* escape non-printable characters */ | ||
| 450 | for (i = 0; i < msg->text_len; i++) { | ||
| 451 | unsigned char c = log_text(msg)[i]; | ||
| 452 | |||
| 453 | if (c < ' ' || c >= 128) | ||
| 454 | len += sprintf(user->buf + len, "\\x%02x", c); | ||
| 455 | else | ||
| 456 | user->buf[len++] = c; | ||
| 457 | } | ||
| 458 | user->buf[len++] = '\n'; | ||
| 459 | |||
| 460 | if (msg->dict_len) { | ||
| 461 | bool line = true; | ||
| 462 | |||
| 463 | for (i = 0; i < msg->dict_len; i++) { | ||
| 464 | unsigned char c = log_dict(msg)[i]; | ||
| 465 | |||
| 466 | if (line) { | ||
| 467 | user->buf[len++] = ' '; | ||
| 468 | line = false; | ||
| 469 | } | ||
| 470 | |||
| 471 | if (c == '\0') { | ||
| 472 | user->buf[len++] = '\n'; | ||
| 473 | line = true; | ||
| 474 | continue; | ||
| 475 | } | ||
| 476 | |||
| 477 | if (c < ' ' || c >= 128) { | ||
| 478 | len += sprintf(user->buf + len, "\\x%02x", c); | ||
| 479 | continue; | ||
| 480 | } | ||
| 481 | |||
| 482 | user->buf[len++] = c; | ||
| 483 | } | ||
| 484 | user->buf[len++] = '\n'; | ||
| 485 | } | ||
| 486 | |||
| 487 | user->idx = log_next(user->idx); | ||
| 488 | user->seq++; | ||
| 489 | raw_spin_unlock(&logbuf_lock); | ||
| 490 | |||
| 491 | if (len > count) { | ||
| 492 | ret = -EINVAL; | ||
| 493 | goto out; | ||
| 494 | } | ||
| 495 | |||
| 496 | if (copy_to_user(buf, user->buf, len)) { | ||
| 497 | ret = -EFAULT; | ||
| 498 | goto out; | ||
| 499 | } | ||
| 500 | ret = len; | ||
| 501 | out: | ||
| 502 | mutex_unlock(&user->lock); | ||
| 503 | return ret; | ||
| 504 | } | ||
| 505 | |||
| 506 | static loff_t devkmsg_llseek(struct file *file, loff_t offset, int whence) | ||
| 507 | { | ||
| 508 | struct devkmsg_user *user = file->private_data; | ||
| 509 | loff_t ret = 0; | ||
| 510 | |||
| 511 | if (!user) | ||
| 512 | return -EBADF; | ||
| 513 | if (offset) | ||
| 514 | return -ESPIPE; | ||
| 515 | |||
| 516 | raw_spin_lock(&logbuf_lock); | ||
| 517 | switch (whence) { | ||
| 518 | case SEEK_SET: | ||
| 519 | /* the first record */ | ||
| 520 | user->idx = log_first_idx; | ||
| 521 | user->seq = log_first_seq; | ||
| 522 | break; | ||
| 523 | case SEEK_DATA: | ||
| 524 | /* | ||
| 525 | * The first record after the last SYSLOG_ACTION_CLEAR, | ||
| 526 | * like issued by 'dmesg -c'. Reading /dev/kmsg itself | ||
| 527 | * changes no global state, and does not clear anything. | ||
| 528 | */ | ||
| 529 | user->idx = clear_idx; | ||
| 530 | user->seq = clear_seq; | ||
| 531 | break; | ||
| 532 | case SEEK_END: | ||
| 533 | /* after the last record */ | ||
| 534 | user->idx = log_next_idx; | ||
| 535 | user->seq = log_next_seq; | ||
| 536 | break; | ||
| 537 | default: | ||
| 538 | ret = -EINVAL; | ||
| 539 | } | ||
| 540 | raw_spin_unlock(&logbuf_lock); | ||
| 541 | return ret; | ||
| 542 | } | ||
| 543 | |||
| 544 | static unsigned int devkmsg_poll(struct file *file, poll_table *wait) | ||
| 545 | { | ||
| 546 | struct devkmsg_user *user = file->private_data; | ||
| 547 | int ret = 0; | ||
| 548 | |||
| 549 | if (!user) | ||
| 550 | return POLLERR|POLLNVAL; | ||
| 551 | |||
| 552 | poll_wait(file, &log_wait, wait); | ||
| 553 | |||
| 554 | raw_spin_lock(&logbuf_lock); | ||
| 555 | if (user->seq < log_next_seq) { | ||
| 556 | /* return error when data has vanished underneath us */ | ||
| 557 | if (user->seq < log_first_seq) | ||
| 558 | ret = POLLIN|POLLRDNORM|POLLERR|POLLPRI; | ||
| 559 | ret = POLLIN|POLLRDNORM; | ||
| 560 | } | ||
| 561 | raw_spin_unlock(&logbuf_lock); | ||
| 562 | |||
| 563 | return ret; | ||
| 564 | } | ||
| 565 | |||
| 566 | static int devkmsg_open(struct inode *inode, struct file *file) | ||
| 567 | { | ||
| 568 | struct devkmsg_user *user; | ||
| 569 | int err; | ||
| 570 | |||
| 571 | /* write-only does not need any file context */ | ||
| 572 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) | ||
| 573 | return 0; | ||
| 574 | |||
| 575 | err = security_syslog(SYSLOG_ACTION_READ_ALL); | ||
| 576 | if (err) | ||
| 577 | return err; | ||
| 578 | |||
| 579 | user = kmalloc(sizeof(struct devkmsg_user), GFP_KERNEL); | ||
| 580 | if (!user) | ||
| 581 | return -ENOMEM; | ||
| 582 | |||
| 583 | mutex_init(&user->lock); | ||
| 584 | |||
| 585 | raw_spin_lock(&logbuf_lock); | ||
| 586 | user->idx = log_first_idx; | ||
| 587 | user->seq = log_first_seq; | ||
| 588 | raw_spin_unlock(&logbuf_lock); | ||
| 589 | |||
| 590 | file->private_data = user; | ||
| 591 | return 0; | ||
| 592 | } | ||
| 593 | |||
| 594 | static int devkmsg_release(struct inode *inode, struct file *file) | ||
| 595 | { | ||
| 596 | struct devkmsg_user *user = file->private_data; | ||
| 597 | |||
| 598 | if (!user) | ||
| 599 | return 0; | ||
| 600 | |||
| 601 | mutex_destroy(&user->lock); | ||
| 602 | kfree(user); | ||
| 603 | return 0; | ||
| 604 | } | ||
| 605 | |||
| 606 | const struct file_operations kmsg_fops = { | ||
| 607 | .open = devkmsg_open, | ||
| 608 | .read = devkmsg_read, | ||
| 609 | .aio_write = devkmsg_writev, | ||
| 610 | .llseek = devkmsg_llseek, | ||
| 611 | .poll = devkmsg_poll, | ||
| 612 | .release = devkmsg_release, | ||
| 613 | }; | ||
| 155 | 614 | ||
| 156 | #ifdef CONFIG_KEXEC | 615 | #ifdef CONFIG_KEXEC |
| 157 | /* | 616 | /* |
| @@ -165,9 +624,9 @@ static int saved_console_loglevel = -1; | |||
| 165 | void log_buf_kexec_setup(void) | 624 | void log_buf_kexec_setup(void) |
| 166 | { | 625 | { |
| 167 | VMCOREINFO_SYMBOL(log_buf); | 626 | VMCOREINFO_SYMBOL(log_buf); |
| 168 | VMCOREINFO_SYMBOL(log_end); | ||
| 169 | VMCOREINFO_SYMBOL(log_buf_len); | 627 | VMCOREINFO_SYMBOL(log_buf_len); |
| 170 | VMCOREINFO_SYMBOL(logged_chars); | 628 | VMCOREINFO_SYMBOL(log_first_idx); |
| 629 | VMCOREINFO_SYMBOL(log_next_idx); | ||
| 171 | } | 630 | } |
| 172 | #endif | 631 | #endif |
| 173 | 632 | ||
| @@ -191,7 +650,6 @@ early_param("log_buf_len", log_buf_len_setup); | |||
| 191 | void __init setup_log_buf(int early) | 650 | void __init setup_log_buf(int early) |
| 192 | { | 651 | { |
| 193 | unsigned long flags; | 652 | unsigned long flags; |
| 194 | unsigned start, dest_idx, offset; | ||
| 195 | char *new_log_buf; | 653 | char *new_log_buf; |
| 196 | int free; | 654 | int free; |
| 197 | 655 | ||
| @@ -219,20 +677,8 @@ void __init setup_log_buf(int early) | |||
| 219 | log_buf_len = new_log_buf_len; | 677 | log_buf_len = new_log_buf_len; |
| 220 | log_buf = new_log_buf; | 678 | log_buf = new_log_buf; |
| 221 | new_log_buf_len = 0; | 679 | new_log_buf_len = 0; |
| 222 | free = __LOG_BUF_LEN - log_end; | 680 | free = __LOG_BUF_LEN - log_next_idx; |
| 223 | 681 | memcpy(log_buf, __log_buf, __LOG_BUF_LEN); | |
| 224 | offset = start = min(con_start, log_start); | ||
| 225 | dest_idx = 0; | ||
| 226 | while (start != log_end) { | ||
| 227 | unsigned log_idx_mask = start & (__LOG_BUF_LEN - 1); | ||
| 228 | |||
| 229 | log_buf[dest_idx] = __log_buf[log_idx_mask]; | ||
| 230 | start++; | ||
| 231 | dest_idx++; | ||
| 232 | } | ||
| 233 | log_start -= offset; | ||
| 234 | con_start -= offset; | ||
| 235 | log_end -= offset; | ||
| 236 | raw_spin_unlock_irqrestore(&logbuf_lock, flags); | 682 | raw_spin_unlock_irqrestore(&logbuf_lock, flags); |
| 237 | 683 | ||
| 238 | pr_info("log_buf_len: %d\n", log_buf_len); | 684 | pr_info("log_buf_len: %d\n", log_buf_len); |
| @@ -332,11 +778,202 @@ static int check_syslog_permissions(int type, bool from_file) | |||
| 332 | return 0; | 778 | return 0; |
| 333 | } | 779 | } |
| 334 | 780 | ||
| 781 | #if defined(CONFIG_PRINTK_TIME) | ||
| 782 | static bool printk_time = 1; | ||
| 783 | #else | ||
| 784 | static bool printk_time; | ||
| 785 | #endif | ||
| 786 | module_param_named(time, printk_time, bool, S_IRUGO | S_IWUSR); | ||
| 787 | |||
| 788 | static size_t print_prefix(const struct log *msg, bool syslog, char *buf) | ||
| 789 | { | ||
| 790 | size_t len = 0; | ||
| 791 | |||
| 792 | if (syslog) { | ||
| 793 | if (buf) { | ||
| 794 | len += sprintf(buf, "<%u>", msg->level); | ||
| 795 | } else { | ||
| 796 | len += 3; | ||
| 797 | if (msg->level > 9) | ||
| 798 | len++; | ||
| 799 | if (msg->level > 99) | ||
| 800 | len++; | ||
| 801 | } | ||
| 802 | } | ||
| 803 | |||
| 804 | if (printk_time) { | ||
| 805 | if (buf) { | ||
| 806 | unsigned long long ts = msg->ts_nsec; | ||
| 807 | unsigned long rem_nsec = do_div(ts, 1000000000); | ||
| 808 | |||
| 809 | len += sprintf(buf + len, "[%5lu.%06lu] ", | ||
| 810 | (unsigned long) ts, rem_nsec / 1000); | ||
| 811 | } else { | ||
| 812 | len += 15; | ||
| 813 | } | ||
| 814 | } | ||
| 815 | |||
| 816 | return len; | ||
| 817 | } | ||
| 818 | |||
| 819 | static size_t msg_print_text(const struct log *msg, bool syslog, | ||
| 820 | char *buf, size_t size) | ||
| 821 | { | ||
| 822 | const char *text = log_text(msg); | ||
| 823 | size_t text_size = msg->text_len; | ||
| 824 | size_t len = 0; | ||
| 825 | |||
| 826 | do { | ||
| 827 | const char *next = memchr(text, '\n', text_size); | ||
| 828 | size_t text_len; | ||
| 829 | |||
| 830 | if (next) { | ||
| 831 | text_len = next - text; | ||
| 832 | next++; | ||
| 833 | text_size -= next - text; | ||
| 834 | } else { | ||
| 835 | text_len = text_size; | ||
| 836 | } | ||
| 837 | |||
| 838 | if (buf) { | ||
| 839 | if (print_prefix(msg, syslog, NULL) + | ||
| 840 | text_len + 1>= size - len) | ||
| 841 | break; | ||
| 842 | |||
| 843 | len += print_prefix(msg, syslog, buf + len); | ||
| 844 | memcpy(buf + len, text, text_len); | ||
| 845 | len += text_len; | ||
| 846 | buf[len++] = '\n'; | ||
| 847 | } else { | ||
| 848 | /* SYSLOG_ACTION_* buffer size only calculation */ | ||
| 849 | len += print_prefix(msg, syslog, NULL); | ||
| 850 | len += text_len + 1; | ||
| 851 | } | ||
| 852 | |||
| 853 | text = next; | ||
| 854 | } while (text); | ||
| 855 | |||
| 856 | return len; | ||
| 857 | } | ||
| 858 | |||
| 859 | static int syslog_print(char __user *buf, int size) | ||
| 860 | { | ||
| 861 | char *text; | ||
| 862 | struct log *msg; | ||
| 863 | int len; | ||
| 864 | |||
| 865 | text = kmalloc(LOG_LINE_MAX, GFP_KERNEL); | ||
| 866 | if (!text) | ||
| 867 | return -ENOMEM; | ||
| 868 | |||
| 869 | raw_spin_lock_irq(&logbuf_lock); | ||
| 870 | if (syslog_seq < log_first_seq) { | ||
| 871 | /* messages are gone, move to first one */ | ||
| 872 | syslog_seq = log_first_seq; | ||
| 873 | syslog_idx = log_first_idx; | ||
| 874 | } | ||
| 875 | msg = log_from_idx(syslog_idx); | ||
| 876 | len = msg_print_text(msg, true, text, LOG_LINE_MAX); | ||
| 877 | syslog_idx = log_next(syslog_idx); | ||
| 878 | syslog_seq++; | ||
| 879 | raw_spin_unlock_irq(&logbuf_lock); | ||
| 880 | |||
| 881 | if (len > 0 && copy_to_user(buf, text, len)) | ||
| 882 | len = -EFAULT; | ||
| 883 | |||
| 884 | kfree(text); | ||
| 885 | return len; | ||
| 886 | } | ||
| 887 | |||
| 888 | static int syslog_print_all(char __user *buf, int size, bool clear) | ||
| 889 | { | ||
| 890 | char *text; | ||
| 891 | int len = 0; | ||
| 892 | |||
| 893 | text = kmalloc(LOG_LINE_MAX, GFP_KERNEL); | ||
| 894 | if (!text) | ||
| 895 | return -ENOMEM; | ||
| 896 | |||
| 897 | raw_spin_lock_irq(&logbuf_lock); | ||
| 898 | if (buf) { | ||
| 899 | u64 next_seq; | ||
| 900 | u64 seq; | ||
| 901 | u32 idx; | ||
| 902 | |||
| 903 | if (clear_seq < log_first_seq) { | ||
| 904 | /* messages are gone, move to first available one */ | ||
| 905 | clear_seq = log_first_seq; | ||
| 906 | clear_idx = log_first_idx; | ||
| 907 | } | ||
| 908 | |||
| 909 | /* | ||
| 910 | * Find first record that fits, including all following records, | ||
| 911 | * into the user-provided buffer for this dump. | ||
| 912 | */ | ||
| 913 | seq = clear_seq; | ||
| 914 | idx = clear_idx; | ||
| 915 | while (seq < log_next_seq) { | ||
| 916 | struct log *msg = log_from_idx(idx); | ||
| 917 | |||
| 918 | len += msg_print_text(msg, true, NULL, 0); | ||
| 919 | idx = log_next(idx); | ||
| 920 | seq++; | ||
| 921 | } | ||
| 922 | seq = clear_seq; | ||
| 923 | idx = clear_idx; | ||
| 924 | while (len > size && seq < log_next_seq) { | ||
| 925 | struct log *msg = log_from_idx(idx); | ||
| 926 | |||
| 927 | len -= msg_print_text(msg, true, NULL, 0); | ||
| 928 | idx = log_next(idx); | ||
| 929 | seq++; | ||
| 930 | } | ||
| 931 | |||
| 932 | /* last message in this dump */ | ||
| 933 | next_seq = log_next_seq; | ||
| 934 | |||
| 935 | len = 0; | ||
| 936 | while (len >= 0 && seq < next_seq) { | ||
| 937 | struct log *msg = log_from_idx(idx); | ||
| 938 | int textlen; | ||
| 939 | |||
| 940 | textlen = msg_print_text(msg, true, text, LOG_LINE_MAX); | ||
| 941 | if (textlen < 0) { | ||
| 942 | len = textlen; | ||
| 943 | break; | ||
| 944 | } | ||
| 945 | idx = log_next(idx); | ||
| 946 | seq++; | ||
| 947 | |||
| 948 | raw_spin_unlock_irq(&logbuf_lock); | ||
| 949 | if (copy_to_user(buf + len, text, textlen)) | ||
| 950 | len = -EFAULT; | ||
| 951 | else | ||
| 952 | len += textlen; | ||
| 953 | raw_spin_lock_irq(&logbuf_lock); | ||
| 954 | |||
| 955 | if (seq < log_first_seq) { | ||
| 956 | /* messages are gone, move to next one */ | ||
| 957 | seq = log_first_seq; | ||
| 958 | idx = log_first_idx; | ||
| 959 | } | ||
| 960 | } | ||
| 961 | } | ||
| 962 | |||
| 963 | if (clear) { | ||
| 964 | clear_seq = log_next_seq; | ||
| 965 | clear_idx = log_next_idx; | ||
| 966 | } | ||
| 967 | raw_spin_unlock_irq(&logbuf_lock); | ||
| 968 | |||
| 969 | kfree(text); | ||
| 970 | return len; | ||
| 971 | } | ||
| 972 | |||
| 335 | int do_syslog(int type, char __user *buf, int len, bool from_file) | 973 | int do_syslog(int type, char __user *buf, int len, bool from_file) |
| 336 | { | 974 | { |
| 337 | unsigned i, j, limit, count; | 975 | bool clear = false; |
| 338 | int do_clear = 0; | 976 | static int saved_console_loglevel = -1; |
| 339 | char c; | ||
| 340 | int error; | 977 | int error; |
| 341 | 978 | ||
| 342 | error = check_syslog_permissions(type, from_file); | 979 | error = check_syslog_permissions(type, from_file); |
| @@ -364,28 +1001,14 @@ int do_syslog(int type, char __user *buf, int len, bool from_file) | |||
| 364 | goto out; | 1001 | goto out; |
| 365 | } | 1002 | } |
| 366 | error = wait_event_interruptible(log_wait, | 1003 | error = wait_event_interruptible(log_wait, |
| 367 | (log_start - log_end)); | 1004 | syslog_seq != log_next_seq); |
| 368 | if (error) | 1005 | if (error) |
| 369 | goto out; | 1006 | goto out; |
| 370 | i = 0; | 1007 | error = syslog_print(buf, len); |
| 371 | raw_spin_lock_irq(&logbuf_lock); | ||
| 372 | while (!error && (log_start != log_end) && i < len) { | ||
| 373 | c = LOG_BUF(log_start); | ||
| 374 | log_start++; | ||
| 375 | raw_spin_unlock_irq(&logbuf_lock); | ||
| 376 | error = __put_user(c,buf); | ||
| 377 | buf++; | ||
| 378 | i++; | ||
| 379 | cond_resched(); | ||
| 380 | raw_spin_lock_irq(&logbuf_lock); | ||
| 381 | } | ||
| 382 | raw_spin_unlock_irq(&logbuf_lock); | ||
| 383 | if (!error) | ||
| 384 | error = i; | ||
| 385 | break; | 1008 | break; |
| 386 | /* Read/clear last kernel messages */ | 1009 | /* Read/clear last kernel messages */ |
| 387 | case SYSLOG_ACTION_READ_CLEAR: | 1010 | case SYSLOG_ACTION_READ_CLEAR: |
| 388 | do_clear = 1; | 1011 | clear = true; |
| 389 | /* FALL THRU */ | 1012 | /* FALL THRU */ |
| 390 | /* Read last kernel messages */ | 1013 | /* Read last kernel messages */ |
| 391 | case SYSLOG_ACTION_READ_ALL: | 1014 | case SYSLOG_ACTION_READ_ALL: |
| @@ -399,52 +1022,11 @@ int do_syslog(int type, char __user *buf, int len, bool from_file) | |||
| 399 | error = -EFAULT; | 1022 | error = -EFAULT; |
| 400 | goto out; | 1023 | goto out; |
| 401 | } | 1024 | } |
| 402 | count = len; | 1025 | error = syslog_print_all(buf, len, clear); |
| 403 | if (count > log_buf_len) | ||
| 404 | count = log_buf_len; | ||
| 405 | raw_spin_lock_irq(&logbuf_lock); | ||
| 406 | if (count > logged_chars) | ||
| 407 | count = logged_chars; | ||
| 408 | if (do_clear) | ||
| 409 | logged_chars = 0; | ||
| 410 | limit = log_end; | ||
| 411 | /* | ||
| 412 | * __put_user() could sleep, and while we sleep | ||
| 413 | * printk() could overwrite the messages | ||
| 414 | * we try to copy to user space. Therefore | ||
| 415 | * the messages are copied in reverse. <manfreds> | ||
| 416 | */ | ||
| 417 | for (i = 0; i < count && !error; i++) { | ||
| 418 | j = limit-1-i; | ||
| 419 | if (j + log_buf_len < log_end) | ||
| 420 | break; | ||
| 421 | c = LOG_BUF(j); | ||
| 422 | raw_spin_unlock_irq(&logbuf_lock); | ||
| 423 | error = __put_user(c,&buf[count-1-i]); | ||
| 424 | cond_resched(); | ||
| 425 | raw_spin_lock_irq(&logbuf_lock); | ||
| 426 | } | ||
| 427 | raw_spin_unlock_irq(&logbuf_lock); | ||
| 428 | if (error) | ||
| 429 | break; | ||
| 430 | error = i; | ||
| 431 | if (i != count) { | ||
| 432 | int offset = count-error; | ||
| 433 | /* buffer overflow during copy, correct user buffer. */ | ||
| 434 | for (i = 0; i < error; i++) { | ||
| 435 | if (__get_user(c,&buf[i+offset]) || | ||
| 436 | __put_user(c,&buf[i])) { | ||
| 437 | error = -EFAULT; | ||
| 438 | break; | ||
| 439 | } | ||
| 440 | cond_resched(); | ||
| 441 | } | ||
| 442 | } | ||
| 443 | break; | 1026 | break; |
| 444 | /* Clear ring buffer */ | 1027 | /* Clear ring buffer */ |
| 445 | case SYSLOG_ACTION_CLEAR: | 1028 | case SYSLOG_ACTION_CLEAR: |
| 446 | logged_chars = 0; | 1029 | syslog_print_all(NULL, 0, true); |
| 447 | break; | ||
| 448 | /* Disable logging to console */ | 1030 | /* Disable logging to console */ |
| 449 | case SYSLOG_ACTION_CONSOLE_OFF: | 1031 | case SYSLOG_ACTION_CONSOLE_OFF: |
| 450 | if (saved_console_loglevel == -1) | 1032 | if (saved_console_loglevel == -1) |
| @@ -472,7 +1054,35 @@ int do_syslog(int type, char __user *buf, int len, bool from_file) | |||
| 472 | break; | 1054 | break; |
| 473 | /* Number of chars in the log buffer */ | 1055 | /* Number of chars in the log buffer */ |
| 474 | case SYSLOG_ACTION_SIZE_UNREAD: | 1056 | case SYSLOG_ACTION_SIZE_UNREAD: |
| 475 | error = log_end - log_start; | 1057 | raw_spin_lock_irq(&logbuf_lock); |
| 1058 | if (syslog_seq < log_first_seq) { | ||
| 1059 | /* messages are gone, move to first one */ | ||
| 1060 | syslog_seq = log_first_seq; | ||
| 1061 | syslog_idx = log_first_idx; | ||
| 1062 | } | ||
| 1063 | if (from_file) { | ||
| 1064 | /* | ||
| 1065 | * Short-cut for poll(/"proc/kmsg") which simply checks | ||
| 1066 | * for pending data, not the size; return the count of | ||
| 1067 | * records, not the length. | ||
| 1068 | */ | ||
| 1069 | error = log_next_idx - syslog_idx; | ||
| 1070 | } else { | ||
| 1071 | u64 seq; | ||
| 1072 | u32 idx; | ||
| 1073 | |||
| 1074 | error = 0; | ||
| 1075 | seq = syslog_seq; | ||
| 1076 | idx = syslog_idx; | ||
| 1077 | while (seq < log_next_seq) { | ||
| 1078 | struct log *msg = log_from_idx(idx); | ||
| 1079 | |||
| 1080 | error += msg_print_text(msg, true, NULL, 0); | ||
| 1081 | idx = log_next(idx); | ||
| 1082 | seq++; | ||
| 1083 | } | ||
| 1084 | } | ||
| 1085 | raw_spin_unlock_irq(&logbuf_lock); | ||
| 476 | break; | 1086 | break; |
| 477 | /* Size of the log buffer */ | 1087 | /* Size of the log buffer */ |
| 478 | case SYSLOG_ACTION_SIZE_BUFFER: | 1088 | case SYSLOG_ACTION_SIZE_BUFFER: |
| @@ -501,29 +1111,11 @@ void kdb_syslog_data(char *syslog_data[4]) | |||
| 501 | { | 1111 | { |
| 502 | syslog_data[0] = log_buf; | 1112 | syslog_data[0] = log_buf; |
| 503 | syslog_data[1] = log_buf + log_buf_len; | 1113 | syslog_data[1] = log_buf + log_buf_len; |
| 504 | syslog_data[2] = log_buf + log_end - | 1114 | syslog_data[2] = log_buf + log_first_idx; |
| 505 | (logged_chars < log_buf_len ? logged_chars : log_buf_len); | 1115 | syslog_data[3] = log_buf + log_next_idx; |
| 506 | syslog_data[3] = log_buf + log_end; | ||
| 507 | } | 1116 | } |
| 508 | #endif /* CONFIG_KGDB_KDB */ | 1117 | #endif /* CONFIG_KGDB_KDB */ |
| 509 | 1118 | ||
| 510 | /* | ||
| 511 | * Call the console drivers on a range of log_buf | ||
| 512 | */ | ||
| 513 | static void __call_console_drivers(unsigned start, unsigned end) | ||
| 514 | { | ||
| 515 | struct console *con; | ||
| 516 | |||
| 517 | for_each_console(con) { | ||
| 518 | if (exclusive_console && con != exclusive_console) | ||
| 519 | continue; | ||
| 520 | if ((con->flags & CON_ENABLED) && con->write && | ||
| 521 | (cpu_online(smp_processor_id()) || | ||
| 522 | (con->flags & CON_ANYTIME))) | ||
| 523 | con->write(con, &LOG_BUF(start), end - start); | ||
| 524 | } | ||
| 525 | } | ||
| 526 | |||
| 527 | static bool __read_mostly ignore_loglevel; | 1119 | static bool __read_mostly ignore_loglevel; |
| 528 | 1120 | ||
| 529 | static int __init ignore_loglevel_setup(char *str) | 1121 | static int __init ignore_loglevel_setup(char *str) |
| @@ -540,142 +1132,33 @@ MODULE_PARM_DESC(ignore_loglevel, "ignore loglevel setting, to" | |||
| 540 | "print all kernel messages to the console."); | 1132 | "print all kernel messages to the console."); |
| 541 | 1133 | ||
| 542 | /* | 1134 | /* |
| 543 | * Write out chars from start to end - 1 inclusive | ||
| 544 | */ | ||
| 545 | static void _call_console_drivers(unsigned start, | ||
| 546 | unsigned end, int msg_log_level) | ||
| 547 | { | ||
| 548 | trace_console(&LOG_BUF(0), start, end, log_buf_len); | ||
| 549 | |||
| 550 | if ((msg_log_level < console_loglevel || ignore_loglevel) && | ||
| 551 | console_drivers && start != end) { | ||
| 552 | if ((start & LOG_BUF_MASK) > (end & LOG_BUF_MASK)) { | ||
| 553 | /* wrapped write */ | ||
| 554 | __call_console_drivers(start & LOG_BUF_MASK, | ||
| 555 | log_buf_len); | ||
| 556 | __call_console_drivers(0, end & LOG_BUF_MASK); | ||
| 557 | } else { | ||
| 558 | __call_console_drivers(start, end); | ||
| 559 | } | ||
| 560 | } | ||
| 561 | } | ||
| 562 | |||
| 563 | /* | ||
| 564 | * Parse the syslog header <[0-9]*>. The decimal value represents 32bit, the | ||
| 565 | * lower 3 bit are the log level, the rest are the log facility. In case | ||
| 566 | * userspace passes usual userspace syslog messages to /dev/kmsg or | ||
| 567 | * /dev/ttyprintk, the log prefix might contain the facility. Printk needs | ||
| 568 | * to extract the correct log level for in-kernel processing, and not mangle | ||
| 569 | * the original value. | ||
| 570 | * | ||
| 571 | * If a prefix is found, the length of the prefix is returned. If 'level' is | ||
| 572 | * passed, it will be filled in with the log level without a possible facility | ||
| 573 | * value. If 'special' is passed, the special printk prefix chars are accepted | ||
| 574 | * and returned. If no valid header is found, 0 is returned and the passed | ||
| 575 | * variables are not touched. | ||
| 576 | */ | ||
| 577 | static size_t log_prefix(const char *p, unsigned int *level, char *special) | ||
| 578 | { | ||
| 579 | unsigned int lev = 0; | ||
| 580 | char sp = '\0'; | ||
| 581 | size_t len; | ||
| 582 | |||
| 583 | if (p[0] != '<' || !p[1]) | ||
| 584 | return 0; | ||
| 585 | if (p[2] == '>') { | ||
| 586 | /* usual single digit level number or special char */ | ||
| 587 | switch (p[1]) { | ||
| 588 | case '0' ... '7': | ||
| 589 | lev = p[1] - '0'; | ||
| 590 | break; | ||
| 591 | case 'c': /* KERN_CONT */ | ||
| 592 | case 'd': /* KERN_DEFAULT */ | ||
| 593 | sp = p[1]; | ||
| 594 | break; | ||
| 595 | default: | ||
| 596 | return 0; | ||
| 597 | } | ||
| 598 | len = 3; | ||
| 599 | } else { | ||
| 600 | /* multi digit including the level and facility number */ | ||
| 601 | char *endp = NULL; | ||
| 602 | |||
| 603 | lev = (simple_strtoul(&p[1], &endp, 10) & 7); | ||
| 604 | if (endp == NULL || endp[0] != '>') | ||
| 605 | return 0; | ||
| 606 | len = (endp + 1) - p; | ||
| 607 | } | ||
| 608 | |||
| 609 | /* do not accept special char if not asked for */ | ||
| 610 | if (sp && !special) | ||
| 611 | return 0; | ||
| 612 | |||
| 613 | if (special) { | ||
| 614 | *special = sp; | ||
| 615 | /* return special char, do not touch level */ | ||
| 616 | if (sp) | ||
| 617 | return len; | ||
| 618 | } | ||
| 619 | |||
| 620 | if (level) | ||
| 621 | *level = lev; | ||
| 622 | return len; | ||
| 623 | } | ||
| 624 | |||
| 625 | /* | ||
| 626 | * Call the console drivers, asking them to write out | 1135 | * Call the console drivers, asking them to write out |
| 627 | * log_buf[start] to log_buf[end - 1]. | 1136 | * log_buf[start] to log_buf[end - 1]. |
| 628 | * The console_lock must be held. | 1137 | * The console_lock must be held. |
| 629 | */ | 1138 | */ |
| 630 | static void call_console_drivers(unsigned start, unsigned end) | 1139 | static void call_console_drivers(int level, const char *text, size_t len) |
| 631 | { | 1140 | { |
| 632 | unsigned cur_index, start_print; | 1141 | struct console *con; |
| 633 | static int msg_level = -1; | ||
| 634 | 1142 | ||
| 635 | BUG_ON(((int)(start - end)) > 0); | 1143 | trace_console(text, 0, len, len); |
| 636 | 1144 | ||
| 637 | cur_index = start; | 1145 | if (level >= console_loglevel && !ignore_loglevel) |
| 638 | start_print = start; | 1146 | return; |
| 639 | while (cur_index != end) { | 1147 | if (!console_drivers) |
| 640 | if (msg_level < 0 && ((end - cur_index) > 2)) { | 1148 | return; |
| 641 | /* strip log prefix */ | ||
| 642 | cur_index += log_prefix(&LOG_BUF(cur_index), &msg_level, NULL); | ||
| 643 | start_print = cur_index; | ||
| 644 | } | ||
| 645 | while (cur_index != end) { | ||
| 646 | char c = LOG_BUF(cur_index); | ||
| 647 | |||
| 648 | cur_index++; | ||
| 649 | if (c == '\n') { | ||
| 650 | if (msg_level < 0) { | ||
| 651 | /* | ||
| 652 | * printk() has already given us loglevel tags in | ||
| 653 | * the buffer. This code is here in case the | ||
| 654 | * log buffer has wrapped right round and scribbled | ||
| 655 | * on those tags | ||
| 656 | */ | ||
| 657 | msg_level = default_message_loglevel; | ||
| 658 | } | ||
| 659 | _call_console_drivers(start_print, cur_index, msg_level); | ||
| 660 | msg_level = -1; | ||
| 661 | start_print = cur_index; | ||
| 662 | break; | ||
| 663 | } | ||
| 664 | } | ||
| 665 | } | ||
| 666 | _call_console_drivers(start_print, end, msg_level); | ||
| 667 | } | ||
| 668 | 1149 | ||
| 669 | static void emit_log_char(char c) | 1150 | for_each_console(con) { |
| 670 | { | 1151 | if (exclusive_console && con != exclusive_console) |
| 671 | LOG_BUF(log_end) = c; | 1152 | continue; |
| 672 | log_end++; | 1153 | if (!(con->flags & CON_ENABLED)) |
| 673 | if (log_end - log_start > log_buf_len) | 1154 | continue; |
| 674 | log_start = log_end - log_buf_len; | 1155 | if (!con->write) |
| 675 | if (log_end - con_start > log_buf_len) | 1156 | continue; |
| 676 | con_start = log_end - log_buf_len; | 1157 | if (!cpu_online(smp_processor_id()) && |
| 677 | if (logged_chars < log_buf_len) | 1158 | !(con->flags & CON_ANYTIME)) |
| 678 | logged_chars++; | 1159 | continue; |
| 1160 | con->write(con, text, len); | ||
| 1161 | } | ||
| 679 | } | 1162 | } |
| 680 | 1163 | ||
| 681 | /* | 1164 | /* |
| @@ -700,16 +1183,6 @@ static void zap_locks(void) | |||
| 700 | sema_init(&console_sem, 1); | 1183 | sema_init(&console_sem, 1); |
| 701 | } | 1184 | } |
| 702 | 1185 | ||
| 703 | #if defined(CONFIG_PRINTK_TIME) | ||
| 704 | static bool printk_time = 1; | ||
| 705 | #else | ||
| 706 | static bool printk_time = 0; | ||
| 707 | #endif | ||
| 708 | module_param_named(time, printk_time, bool, S_IRUGO | S_IWUSR); | ||
| 709 | |||
| 710 | static bool always_kmsg_dump; | ||
| 711 | module_param_named(always_kmsg_dump, always_kmsg_dump, bool, S_IRUGO | S_IWUSR); | ||
| 712 | |||
| 713 | /* Check if we have any console registered that can be called early in boot. */ | 1186 | /* Check if we have any console registered that can be called early in boot. */ |
| 714 | static int have_callable_console(void) | 1187 | static int have_callable_console(void) |
| 715 | { | 1188 | { |
| @@ -722,51 +1195,6 @@ static int have_callable_console(void) | |||
| 722 | return 0; | 1195 | return 0; |
| 723 | } | 1196 | } |
| 724 | 1197 | ||
| 725 | /** | ||
| 726 | * printk - print a kernel message | ||
| 727 | * @fmt: format string | ||
| 728 | * | ||
| 729 | * This is printk(). It can be called from any context. We want it to work. | ||
| 730 | * | ||
| 731 | * We try to grab the console_lock. If we succeed, it's easy - we log the output and | ||
| 732 | * call the console drivers. If we fail to get the semaphore we place the output | ||
| 733 | * into the log buffer and return. The current holder of the console_sem will | ||
| 734 | * notice the new output in console_unlock(); and will send it to the | ||
| 735 | * consoles before releasing the lock. | ||
| 736 | * | ||
| 737 | * One effect of this deferred printing is that code which calls printk() and | ||
| 738 | * then changes console_loglevel may break. This is because console_loglevel | ||
| 739 | * is inspected when the actual printing occurs. | ||
| 740 | * | ||
| 741 | * See also: | ||
| 742 | * printf(3) | ||
| 743 | * | ||
| 744 | * See the vsnprintf() documentation for format string extensions over C99. | ||
| 745 | */ | ||
| 746 | |||
| 747 | asmlinkage int printk(const char *fmt, ...) | ||
| 748 | { | ||
| 749 | va_list args; | ||
| 750 | int r; | ||
| 751 | |||
| 752 | #ifdef CONFIG_KGDB_KDB | ||
| 753 | if (unlikely(kdb_trap_printk)) { | ||
| 754 | va_start(args, fmt); | ||
| 755 | r = vkdb_printf(fmt, args); | ||
| 756 | va_end(args); | ||
| 757 | return r; | ||
| 758 | } | ||
| 759 | #endif | ||
| 760 | va_start(args, fmt); | ||
| 761 | r = vprintk(fmt, args); | ||
| 762 | va_end(args); | ||
| 763 | |||
| 764 | return r; | ||
| 765 | } | ||
| 766 | |||
| 767 | /* cpu currently holding logbuf_lock */ | ||
| 768 | static volatile unsigned int printk_cpu = UINT_MAX; | ||
| 769 | |||
| 770 | /* | 1198 | /* |
| 771 | * Can we actually use the console at this time on this cpu? | 1199 | * Can we actually use the console at this time on this cpu? |
| 772 | * | 1200 | * |
| @@ -810,17 +1238,12 @@ static int console_trylock_for_printk(unsigned int cpu) | |||
| 810 | retval = 0; | 1238 | retval = 0; |
| 811 | } | 1239 | } |
| 812 | } | 1240 | } |
| 813 | printk_cpu = UINT_MAX; | 1241 | logbuf_cpu = UINT_MAX; |
| 814 | if (wake) | 1242 | if (wake) |
| 815 | up(&console_sem); | 1243 | up(&console_sem); |
| 816 | raw_spin_unlock(&logbuf_lock); | 1244 | raw_spin_unlock(&logbuf_lock); |
| 817 | return retval; | 1245 | return retval; |
| 818 | } | 1246 | } |
| 819 | static const char recursion_bug_msg [] = | ||
| 820 | KERN_CRIT "BUG: recent printk recursion!\n"; | ||
| 821 | static int recursion_bug; | ||
| 822 | static int new_text_line = 1; | ||
| 823 | static char printk_buf[1024]; | ||
| 824 | 1247 | ||
| 825 | int printk_delay_msec __read_mostly; | 1248 | int printk_delay_msec __read_mostly; |
| 826 | 1249 | ||
| @@ -836,15 +1259,23 @@ static inline void printk_delay(void) | |||
| 836 | } | 1259 | } |
| 837 | } | 1260 | } |
| 838 | 1261 | ||
| 839 | asmlinkage int vprintk(const char *fmt, va_list args) | 1262 | asmlinkage int vprintk_emit(int facility, int level, |
| 1263 | const char *dict, size_t dictlen, | ||
| 1264 | const char *fmt, va_list args) | ||
| 840 | { | 1265 | { |
| 841 | int printed_len = 0; | 1266 | static int recursion_bug; |
| 842 | int current_log_level = default_message_loglevel; | 1267 | static char cont_buf[LOG_LINE_MAX]; |
| 1268 | static size_t cont_len; | ||
| 1269 | static int cont_level; | ||
| 1270 | static struct task_struct *cont_task; | ||
| 1271 | static char textbuf[LOG_LINE_MAX]; | ||
| 1272 | char *text = textbuf; | ||
| 1273 | size_t text_len; | ||
| 843 | unsigned long flags; | 1274 | unsigned long flags; |
| 844 | int this_cpu; | 1275 | int this_cpu; |
| 845 | char *p; | 1276 | bool newline = false; |
| 846 | size_t plen; | 1277 | bool prefix = false; |
| 847 | char special; | 1278 | int printed_len = 0; |
| 848 | 1279 | ||
| 849 | boot_delay_msec(); | 1280 | boot_delay_msec(); |
| 850 | printk_delay(); | 1281 | printk_delay(); |
| @@ -856,7 +1287,7 @@ asmlinkage int vprintk(const char *fmt, va_list args) | |||
| 856 | /* | 1287 | /* |
| 857 | * Ouch, printk recursed into itself! | 1288 | * Ouch, printk recursed into itself! |
| 858 | */ | 1289 | */ |
| 859 | if (unlikely(printk_cpu == this_cpu)) { | 1290 | if (unlikely(logbuf_cpu == this_cpu)) { |
| 860 | /* | 1291 | /* |
| 861 | * If a crash is occurring during printk() on this CPU, | 1292 | * If a crash is occurring during printk() on this CPU, |
| 862 | * then try to get the crash message out but make sure | 1293 | * then try to get the crash message out but make sure |
| @@ -873,97 +1304,110 @@ asmlinkage int vprintk(const char *fmt, va_list args) | |||
| 873 | 1304 | ||
| 874 | lockdep_off(); | 1305 | lockdep_off(); |
| 875 | raw_spin_lock(&logbuf_lock); | 1306 | raw_spin_lock(&logbuf_lock); |
| 876 | printk_cpu = this_cpu; | 1307 | logbuf_cpu = this_cpu; |
| 877 | 1308 | ||
| 878 | if (recursion_bug) { | 1309 | if (recursion_bug) { |
| 1310 | static const char recursion_msg[] = | ||
| 1311 | "BUG: recent printk recursion!"; | ||
| 1312 | |||
| 879 | recursion_bug = 0; | 1313 | recursion_bug = 0; |
| 880 | strcpy(printk_buf, recursion_bug_msg); | 1314 | printed_len += strlen(recursion_msg); |
| 881 | printed_len = strlen(recursion_bug_msg); | 1315 | /* emit KERN_CRIT message */ |
| 1316 | log_store(0, 2, NULL, 0, recursion_msg, printed_len); | ||
| 882 | } | 1317 | } |
| 883 | /* Emit the output into the temporary buffer */ | ||
| 884 | printed_len += vscnprintf(printk_buf + printed_len, | ||
| 885 | sizeof(printk_buf) - printed_len, fmt, args); | ||
| 886 | 1318 | ||
| 887 | p = printk_buf; | 1319 | /* |
| 1320 | * The printf needs to come first; we need the syslog | ||
| 1321 | * prefix which might be passed-in as a parameter. | ||
| 1322 | */ | ||
| 1323 | text_len = vscnprintf(text, sizeof(textbuf), fmt, args); | ||
| 888 | 1324 | ||
| 889 | /* Read log level and handle special printk prefix */ | 1325 | /* mark and strip a trailing newline */ |
| 890 | plen = log_prefix(p, ¤t_log_level, &special); | 1326 | if (text_len && text[text_len-1] == '\n') { |
| 891 | if (plen) { | 1327 | text_len--; |
| 892 | p += plen; | 1328 | newline = true; |
| 1329 | } | ||
| 893 | 1330 | ||
| 894 | switch (special) { | 1331 | /* strip syslog prefix and extract log level or control flags */ |
| 895 | case 'c': /* Strip <c> KERN_CONT, continue line */ | 1332 | if (text[0] == '<' && text[1] && text[2] == '>') { |
| 896 | plen = 0; | 1333 | switch (text[1]) { |
| 897 | break; | 1334 | case '0' ... '7': |
| 898 | case 'd': /* Strip <d> KERN_DEFAULT, start new line */ | 1335 | if (level == -1) |
| 899 | plen = 0; | 1336 | level = text[1] - '0'; |
| 900 | default: | 1337 | case 'd': /* KERN_DEFAULT */ |
| 901 | if (!new_text_line) { | 1338 | prefix = true; |
| 902 | emit_log_char('\n'); | 1339 | case 'c': /* KERN_CONT */ |
| 903 | new_text_line = 1; | 1340 | text += 3; |
| 904 | } | 1341 | text_len -= 3; |
| 905 | } | 1342 | } |
| 906 | } | 1343 | } |
| 907 | 1344 | ||
| 908 | /* | 1345 | if (level == -1) |
| 909 | * Copy the output into log_buf. If the caller didn't provide | 1346 | level = default_message_loglevel; |
| 910 | * the appropriate log prefix, we insert them here | ||
| 911 | */ | ||
| 912 | for (; *p; p++) { | ||
| 913 | if (new_text_line) { | ||
| 914 | new_text_line = 0; | ||
| 915 | |||
| 916 | if (plen) { | ||
| 917 | /* Copy original log prefix */ | ||
| 918 | int i; | ||
| 919 | |||
| 920 | for (i = 0; i < plen; i++) | ||
| 921 | emit_log_char(printk_buf[i]); | ||
| 922 | printed_len += plen; | ||
| 923 | } else { | ||
| 924 | /* Add log prefix */ | ||
| 925 | emit_log_char('<'); | ||
| 926 | emit_log_char(current_log_level + '0'); | ||
| 927 | emit_log_char('>'); | ||
| 928 | printed_len += 3; | ||
| 929 | } | ||
| 930 | 1347 | ||
| 931 | if (printk_time) { | 1348 | if (dict) { |
| 932 | /* Add the current time stamp */ | 1349 | prefix = true; |
| 933 | char tbuf[50], *tp; | 1350 | newline = true; |
| 934 | unsigned tlen; | 1351 | } |
| 935 | unsigned long long t; | ||
| 936 | unsigned long nanosec_rem; | ||
| 937 | |||
| 938 | t = cpu_clock(printk_cpu); | ||
| 939 | nanosec_rem = do_div(t, 1000000000); | ||
| 940 | tlen = sprintf(tbuf, "[%5lu.%06lu] ", | ||
| 941 | (unsigned long) t, | ||
| 942 | nanosec_rem / 1000); | ||
| 943 | |||
| 944 | for (tp = tbuf; tp < tbuf + tlen; tp++) | ||
| 945 | emit_log_char(*tp); | ||
| 946 | printed_len += tlen; | ||
| 947 | } | ||
| 948 | 1352 | ||
| 949 | if (!*p) | 1353 | if (!newline) { |
| 950 | break; | 1354 | if (cont_len && (prefix || cont_task != current)) { |
| 1355 | /* | ||
| 1356 | * Flush earlier buffer, which is either from a | ||
| 1357 | * different thread, or when we got a new prefix. | ||
| 1358 | */ | ||
| 1359 | log_store(facility, cont_level, NULL, 0, cont_buf, cont_len); | ||
| 1360 | cont_len = 0; | ||
| 951 | } | 1361 | } |
| 952 | 1362 | ||
| 953 | emit_log_char(*p); | 1363 | if (!cont_len) { |
| 954 | if (*p == '\n') | 1364 | cont_level = level; |
| 955 | new_text_line = 1; | 1365 | cont_task = current; |
| 1366 | } | ||
| 1367 | |||
| 1368 | /* buffer or append to earlier buffer from the same thread */ | ||
| 1369 | if (cont_len + text_len > sizeof(cont_buf)) | ||
| 1370 | text_len = sizeof(cont_buf) - cont_len; | ||
| 1371 | memcpy(cont_buf + cont_len, text, text_len); | ||
| 1372 | cont_len += text_len; | ||
| 1373 | } else { | ||
| 1374 | if (cont_len && cont_task == current) { | ||
| 1375 | if (prefix) { | ||
| 1376 | /* | ||
| 1377 | * New prefix from the same thread; flush. We | ||
| 1378 | * either got no earlier newline, or we race | ||
| 1379 | * with an interrupt. | ||
| 1380 | */ | ||
| 1381 | log_store(facility, cont_level, | ||
| 1382 | NULL, 0, cont_buf, cont_len); | ||
| 1383 | cont_len = 0; | ||
| 1384 | } | ||
| 1385 | |||
| 1386 | /* append to the earlier buffer and flush */ | ||
| 1387 | if (cont_len + text_len > sizeof(cont_buf)) | ||
| 1388 | text_len = sizeof(cont_buf) - cont_len; | ||
| 1389 | memcpy(cont_buf + cont_len, text, text_len); | ||
| 1390 | cont_len += text_len; | ||
| 1391 | log_store(facility, cont_level, | ||
| 1392 | NULL, 0, cont_buf, cont_len); | ||
| 1393 | cont_len = 0; | ||
| 1394 | cont_task = NULL; | ||
| 1395 | printed_len = cont_len; | ||
| 1396 | } else { | ||
| 1397 | /* ordinary single and terminated line */ | ||
| 1398 | log_store(facility, level, | ||
| 1399 | dict, dictlen, text, text_len); | ||
| 1400 | printed_len = text_len; | ||
| 1401 | } | ||
| 956 | } | 1402 | } |
| 957 | 1403 | ||
| 958 | /* | 1404 | /* |
| 959 | * Try to acquire and then immediately release the | 1405 | * Try to acquire and then immediately release the console semaphore. |
| 960 | * console semaphore. The release will do all the | 1406 | * The release will print out buffers and wake up /dev/kmsg and syslog() |
| 961 | * actual magic (print out buffers, wake up klogd, | 1407 | * users. |
| 962 | * etc). | ||
| 963 | * | 1408 | * |
| 964 | * The console_trylock_for_printk() function | 1409 | * The console_trylock_for_printk() function will release 'logbuf_lock' |
| 965 | * will release 'logbuf_lock' regardless of whether it | 1410 | * regardless of whether it actually gets the console semaphore or not. |
| 966 | * actually gets the semaphore or not. | ||
| 967 | */ | 1411 | */ |
| 968 | if (console_trylock_for_printk(this_cpu)) | 1412 | if (console_trylock_for_printk(this_cpu)) |
| 969 | console_unlock(); | 1413 | console_unlock(); |
| @@ -974,16 +1418,81 @@ out_restore_irqs: | |||
| 974 | 1418 | ||
| 975 | return printed_len; | 1419 | return printed_len; |
| 976 | } | 1420 | } |
| 977 | EXPORT_SYMBOL(printk); | 1421 | EXPORT_SYMBOL(vprintk_emit); |
| 978 | EXPORT_SYMBOL(vprintk); | ||
| 979 | 1422 | ||
| 980 | #else | 1423 | asmlinkage int vprintk(const char *fmt, va_list args) |
| 1424 | { | ||
| 1425 | return vprintk_emit(0, -1, NULL, 0, fmt, args); | ||
| 1426 | } | ||
| 1427 | EXPORT_SYMBOL(vprintk); | ||
| 981 | 1428 | ||
| 982 | static void call_console_drivers(unsigned start, unsigned end) | 1429 | asmlinkage int printk_emit(int facility, int level, |
| 1430 | const char *dict, size_t dictlen, | ||
| 1431 | const char *fmt, ...) | ||
| 983 | { | 1432 | { |
| 1433 | va_list args; | ||
| 1434 | int r; | ||
| 1435 | |||
| 1436 | va_start(args, fmt); | ||
| 1437 | r = vprintk_emit(facility, level, dict, dictlen, fmt, args); | ||
| 1438 | va_end(args); | ||
| 1439 | |||
| 1440 | return r; | ||
| 984 | } | 1441 | } |
| 1442 | EXPORT_SYMBOL(printk_emit); | ||
| 985 | 1443 | ||
| 1444 | /** | ||
| 1445 | * printk - print a kernel message | ||
| 1446 | * @fmt: format string | ||
| 1447 | * | ||
| 1448 | * This is printk(). It can be called from any context. We want it to work. | ||
| 1449 | * | ||
| 1450 | * We try to grab the console_lock. If we succeed, it's easy - we log the | ||
| 1451 | * output and call the console drivers. If we fail to get the semaphore, we | ||
| 1452 | * place the output into the log buffer and return. The current holder of | ||
| 1453 | * the console_sem will notice the new output in console_unlock(); and will | ||
| 1454 | * send it to the consoles before releasing the lock. | ||
| 1455 | * | ||
| 1456 | * One effect of this deferred printing is that code which calls printk() and | ||
| 1457 | * then changes console_loglevel may break. This is because console_loglevel | ||
| 1458 | * is inspected when the actual printing occurs. | ||
| 1459 | * | ||
| 1460 | * See also: | ||
| 1461 | * printf(3) | ||
| 1462 | * | ||
| 1463 | * See the vsnprintf() documentation for format string extensions over C99. | ||
| 1464 | */ | ||
| 1465 | asmlinkage int printk(const char *fmt, ...) | ||
| 1466 | { | ||
| 1467 | va_list args; | ||
| 1468 | int r; | ||
| 1469 | |||
| 1470 | #ifdef CONFIG_KGDB_KDB | ||
| 1471 | if (unlikely(kdb_trap_printk)) { | ||
| 1472 | va_start(args, fmt); | ||
| 1473 | r = vkdb_printf(fmt, args); | ||
| 1474 | va_end(args); | ||
| 1475 | return r; | ||
| 1476 | } | ||
| 986 | #endif | 1477 | #endif |
| 1478 | va_start(args, fmt); | ||
| 1479 | r = vprintk_emit(0, -1, NULL, 0, fmt, args); | ||
| 1480 | va_end(args); | ||
| 1481 | |||
| 1482 | return r; | ||
| 1483 | } | ||
| 1484 | EXPORT_SYMBOL(printk); | ||
| 1485 | |||
| 1486 | #else | ||
| 1487 | |||
| 1488 | #define LOG_LINE_MAX 0 | ||
| 1489 | static struct log *log_from_idx(u32 idx) { return NULL; } | ||
| 1490 | static u32 log_next(u32 idx) { return 0; } | ||
| 1491 | static void call_console_drivers(int level, const char *text, size_t len) {} | ||
| 1492 | static size_t msg_print_text(const struct log *msg, bool syslog, | ||
| 1493 | char *buf, size_t size) { return 0; } | ||
| 1494 | |||
| 1495 | #endif /* CONFIG_PRINTK */ | ||
| 987 | 1496 | ||
| 988 | static int __add_preferred_console(char *name, int idx, char *options, | 1497 | static int __add_preferred_console(char *name, int idx, char *options, |
| 989 | char *brl_options) | 1498 | char *brl_options) |
| @@ -1217,7 +1726,7 @@ int is_console_locked(void) | |||
| 1217 | } | 1726 | } |
| 1218 | 1727 | ||
| 1219 | /* | 1728 | /* |
| 1220 | * Delayed printk facility, for scheduler-internal messages: | 1729 | * Delayed printk version, for scheduler-internal messages: |
| 1221 | */ | 1730 | */ |
| 1222 | #define PRINTK_BUF_SIZE 512 | 1731 | #define PRINTK_BUF_SIZE 512 |
| 1223 | 1732 | ||
| @@ -1253,6 +1762,10 @@ void wake_up_klogd(void) | |||
| 1253 | this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP); | 1762 | this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP); |
| 1254 | } | 1763 | } |
| 1255 | 1764 | ||
| 1765 | /* the next printk record to write to the console */ | ||
| 1766 | static u64 console_seq; | ||
| 1767 | static u32 console_idx; | ||
| 1768 | |||
| 1256 | /** | 1769 | /** |
| 1257 | * console_unlock - unlock the console system | 1770 | * console_unlock - unlock the console system |
| 1258 | * | 1771 | * |
| @@ -1263,15 +1776,16 @@ void wake_up_klogd(void) | |||
| 1263 | * by printk(). If this is the case, console_unlock(); emits | 1776 | * by printk(). If this is the case, console_unlock(); emits |
| 1264 | * the output prior to releasing the lock. | 1777 | * the output prior to releasing the lock. |
| 1265 | * | 1778 | * |
| 1266 | * If there is output waiting for klogd, we wake it up. | 1779 | * If there is output waiting, we wake /dev/kmsg and syslog() users. |
| 1267 | * | 1780 | * |
| 1268 | * console_unlock(); may be called from any context. | 1781 | * console_unlock(); may be called from any context. |
| 1269 | */ | 1782 | */ |
| 1270 | void console_unlock(void) | 1783 | void console_unlock(void) |
| 1271 | { | 1784 | { |
| 1785 | static u64 seen_seq; | ||
| 1272 | unsigned long flags; | 1786 | unsigned long flags; |
| 1273 | unsigned _con_start, _log_end; | 1787 | bool wake_klogd = false; |
| 1274 | unsigned wake_klogd = 0, retry = 0; | 1788 | bool retry; |
| 1275 | 1789 | ||
| 1276 | if (console_suspended) { | 1790 | if (console_suspended) { |
| 1277 | up(&console_sem); | 1791 | up(&console_sem); |
| @@ -1281,17 +1795,38 @@ void console_unlock(void) | |||
| 1281 | console_may_schedule = 0; | 1795 | console_may_schedule = 0; |
| 1282 | 1796 | ||
| 1283 | again: | 1797 | again: |
| 1284 | for ( ; ; ) { | 1798 | for (;;) { |
| 1799 | struct log *msg; | ||
| 1800 | static char text[LOG_LINE_MAX]; | ||
| 1801 | size_t len; | ||
| 1802 | int level; | ||
| 1803 | |||
| 1285 | raw_spin_lock_irqsave(&logbuf_lock, flags); | 1804 | raw_spin_lock_irqsave(&logbuf_lock, flags); |
| 1286 | wake_klogd |= log_start - log_end; | 1805 | if (seen_seq != log_next_seq) { |
| 1287 | if (con_start == log_end) | 1806 | wake_klogd = true; |
| 1288 | break; /* Nothing to print */ | 1807 | seen_seq = log_next_seq; |
| 1289 | _con_start = con_start; | 1808 | } |
| 1290 | _log_end = log_end; | 1809 | |
| 1291 | con_start = log_end; /* Flush */ | 1810 | if (console_seq < log_first_seq) { |
| 1811 | /* messages are gone, move to first one */ | ||
| 1812 | console_seq = log_first_seq; | ||
| 1813 | console_idx = log_first_idx; | ||
| 1814 | } | ||
| 1815 | |||
| 1816 | if (console_seq == log_next_seq) | ||
| 1817 | break; | ||
| 1818 | |||
| 1819 | msg = log_from_idx(console_idx); | ||
| 1820 | level = msg->level & 7; | ||
| 1821 | |||
| 1822 | len = msg_print_text(msg, false, text, sizeof(text)); | ||
| 1823 | |||
| 1824 | console_idx = log_next(console_idx); | ||
| 1825 | console_seq++; | ||
| 1292 | raw_spin_unlock(&logbuf_lock); | 1826 | raw_spin_unlock(&logbuf_lock); |
| 1827 | |||
| 1293 | stop_critical_timings(); /* don't trace print latency */ | 1828 | stop_critical_timings(); /* don't trace print latency */ |
| 1294 | call_console_drivers(_con_start, _log_end); | 1829 | call_console_drivers(level, text, len); |
| 1295 | start_critical_timings(); | 1830 | start_critical_timings(); |
| 1296 | local_irq_restore(flags); | 1831 | local_irq_restore(flags); |
| 1297 | } | 1832 | } |
| @@ -1312,8 +1847,7 @@ again: | |||
| 1312 | * flush, no worries. | 1847 | * flush, no worries. |
| 1313 | */ | 1848 | */ |
| 1314 | raw_spin_lock(&logbuf_lock); | 1849 | raw_spin_lock(&logbuf_lock); |
| 1315 | if (con_start != log_end) | 1850 | retry = console_seq != log_next_seq; |
| 1316 | retry = 1; | ||
| 1317 | raw_spin_unlock_irqrestore(&logbuf_lock, flags); | 1851 | raw_spin_unlock_irqrestore(&logbuf_lock, flags); |
| 1318 | 1852 | ||
| 1319 | if (retry && console_trylock()) | 1853 | if (retry && console_trylock()) |
| @@ -1549,7 +2083,8 @@ void register_console(struct console *newcon) | |||
| 1549 | * for us. | 2083 | * for us. |
| 1550 | */ | 2084 | */ |
| 1551 | raw_spin_lock_irqsave(&logbuf_lock, flags); | 2085 | raw_spin_lock_irqsave(&logbuf_lock, flags); |
| 1552 | con_start = log_start; | 2086 | console_seq = syslog_seq; |
| 2087 | console_idx = syslog_idx; | ||
| 1553 | raw_spin_unlock_irqrestore(&logbuf_lock, flags); | 2088 | raw_spin_unlock_irqrestore(&logbuf_lock, flags); |
| 1554 | /* | 2089 | /* |
| 1555 | * We're about to replay the log buffer. Only do this to the | 2090 | * We're about to replay the log buffer. Only do this to the |
| @@ -1758,6 +2293,9 @@ int kmsg_dump_unregister(struct kmsg_dumper *dumper) | |||
| 1758 | } | 2293 | } |
| 1759 | EXPORT_SYMBOL_GPL(kmsg_dump_unregister); | 2294 | EXPORT_SYMBOL_GPL(kmsg_dump_unregister); |
| 1760 | 2295 | ||
| 2296 | static bool always_kmsg_dump; | ||
| 2297 | module_param_named(always_kmsg_dump, always_kmsg_dump, bool, S_IRUGO | S_IWUSR); | ||
| 2298 | |||
| 1761 | /** | 2299 | /** |
| 1762 | * kmsg_dump - dump kernel log to kernel message dumpers. | 2300 | * kmsg_dump - dump kernel log to kernel message dumpers. |
| 1763 | * @reason: the reason (oops, panic etc) for dumping | 2301 | * @reason: the reason (oops, panic etc) for dumping |
| @@ -1767,8 +2305,7 @@ EXPORT_SYMBOL_GPL(kmsg_dump_unregister); | |||
| 1767 | */ | 2305 | */ |
| 1768 | void kmsg_dump(enum kmsg_dump_reason reason) | 2306 | void kmsg_dump(enum kmsg_dump_reason reason) |
| 1769 | { | 2307 | { |
| 1770 | unsigned long end; | 2308 | u64 idx; |
| 1771 | unsigned chars; | ||
| 1772 | struct kmsg_dumper *dumper; | 2309 | struct kmsg_dumper *dumper; |
| 1773 | const char *s1, *s2; | 2310 | const char *s1, *s2; |
| 1774 | unsigned long l1, l2; | 2311 | unsigned long l1, l2; |
| @@ -1780,24 +2317,27 @@ void kmsg_dump(enum kmsg_dump_reason reason) | |||
| 1780 | /* Theoretically, the log could move on after we do this, but | 2317 | /* Theoretically, the log could move on after we do this, but |
| 1781 | there's not a lot we can do about that. The new messages | 2318 | there's not a lot we can do about that. The new messages |
| 1782 | will overwrite the start of what we dump. */ | 2319 | will overwrite the start of what we dump. */ |
| 2320 | |||
| 1783 | raw_spin_lock_irqsave(&logbuf_lock, flags); | 2321 | raw_spin_lock_irqsave(&logbuf_lock, flags); |
| 1784 | end = log_end & LOG_BUF_MASK; | 2322 | if (syslog_seq < log_first_seq) |
| 1785 | chars = logged_chars; | 2323 | idx = syslog_idx; |
| 1786 | raw_spin_unlock_irqrestore(&logbuf_lock, flags); | 2324 | else |
| 2325 | idx = log_first_idx; | ||
| 1787 | 2326 | ||
| 1788 | if (chars > end) { | 2327 | if (idx > log_next_idx) { |
| 1789 | s1 = log_buf + log_buf_len - chars + end; | 2328 | s1 = log_buf; |
| 1790 | l1 = chars - end; | 2329 | l1 = log_next_idx; |
| 1791 | 2330 | ||
| 1792 | s2 = log_buf; | 2331 | s2 = log_buf + idx; |
| 1793 | l2 = end; | 2332 | l2 = log_buf_len - idx; |
| 1794 | } else { | 2333 | } else { |
| 1795 | s1 = ""; | 2334 | s1 = ""; |
| 1796 | l1 = 0; | 2335 | l1 = 0; |
| 1797 | 2336 | ||
| 1798 | s2 = log_buf + end - chars; | 2337 | s2 = log_buf + idx; |
| 1799 | l2 = chars; | 2338 | l2 = log_next_idx - idx; |
| 1800 | } | 2339 | } |
| 2340 | raw_spin_unlock_irqrestore(&logbuf_lock, flags); | ||
| 1801 | 2341 | ||
| 1802 | rcu_read_lock(); | 2342 | rcu_read_lock(); |
| 1803 | list_for_each_entry_rcu(dumper, &dump_list, list) | 2343 | list_for_each_entry_rcu(dumper, &dump_list, list) |
diff --git a/lib/Kconfig b/lib/Kconfig index 4a8aba2e5cc0..0e25c03939e3 100644 --- a/lib/Kconfig +++ b/lib/Kconfig | |||
| @@ -353,6 +353,14 @@ config CORDIC | |||
| 353 | This option provides an implementation of the CORDIC algorithm; | 353 | This option provides an implementation of the CORDIC algorithm; |
| 354 | calculations are in fixed point. Module will be called cordic. | 354 | calculations are in fixed point. Module will be called cordic. |
| 355 | 355 | ||
| 356 | config DDR | ||
| 357 | bool "JEDEC DDR data" | ||
| 358 | help | ||
| 359 | Data from JEDEC specs for DDR SDRAM memories, | ||
| 360 | particularly the AC timing parameters and addressing | ||
| 361 | information. This data is useful for drivers handling | ||
| 362 | DDR SDRAM controllers. | ||
| 363 | |||
| 356 | config MPILIB | 364 | config MPILIB |
| 357 | tristate | 365 | tristate |
| 358 | select CLZ_TAB | 366 | select CLZ_TAB |
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 6777153f18f3..e11934177030 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug | |||
| @@ -3,12 +3,16 @@ config PRINTK_TIME | |||
| 3 | bool "Show timing information on printks" | 3 | bool "Show timing information on printks" |
| 4 | depends on PRINTK | 4 | depends on PRINTK |
| 5 | help | 5 | help |
| 6 | Selecting this option causes timing information to be | 6 | Selecting this option causes time stamps of the printk() |
| 7 | included in printk output. This allows you to measure | 7 | messages to be added to the output of the syslog() system |
| 8 | the interval between kernel operations, including bootup | 8 | call and at the console. |
| 9 | operations. This is useful for identifying long delays | 9 | |
| 10 | in kernel startup. Or add printk.time=1 at boot-time. | 10 | The timestamp is always recorded internally, and exported |
| 11 | See Documentation/kernel-parameters.txt | 11 | to /dev/kmsg. This flag just specifies if the timestamp should |
| 12 | be included, not that the timestamp is recorded. | ||
| 13 | |||
| 14 | The behavior is also controlled by the kernel command line | ||
| 15 | parameter printk.time=1. See Documentation/kernel-parameters.txt | ||
| 12 | 16 | ||
| 13 | config DEFAULT_MESSAGE_LOGLEVEL | 17 | config DEFAULT_MESSAGE_LOGLEVEL |
| 14 | int "Default message log level (1-7)" | 18 | int "Default message log level (1-7)" |
| @@ -1205,8 +1209,13 @@ config DYNAMIC_DEBUG | |||
| 1205 | otherwise be available at runtime. These messages can then be | 1209 | otherwise be available at runtime. These messages can then be |
| 1206 | enabled/disabled based on various levels of scope - per source file, | 1210 | enabled/disabled based on various levels of scope - per source file, |
| 1207 | function, module, format string, and line number. This mechanism | 1211 | function, module, format string, and line number. This mechanism |
| 1208 | implicitly enables all pr_debug() and dev_dbg() calls. The impact of | 1212 | implicitly compiles in all pr_debug() and dev_dbg() calls, which |
| 1209 | this compile option is a larger kernel text size of about 2%. | 1213 | enlarges the kernel text size by about 2%. |
| 1214 | |||
| 1215 | If a source file is compiled with DEBUG flag set, any | ||
| 1216 | pr_debug() calls in it are enabled by default, but can be | ||
| 1217 | disabled at runtime as below. Note that DEBUG flag is | ||
| 1218 | turned on by many CONFIG_*DEBUG* options. | ||
| 1210 | 1219 | ||
| 1211 | Usage: | 1220 | Usage: |
| 1212 | 1221 | ||
| @@ -1223,16 +1232,16 @@ config DYNAMIC_DEBUG | |||
| 1223 | lineno : line number of the debug statement | 1232 | lineno : line number of the debug statement |
| 1224 | module : module that contains the debug statement | 1233 | module : module that contains the debug statement |
| 1225 | function : function that contains the debug statement | 1234 | function : function that contains the debug statement |
| 1226 | flags : 'p' means the line is turned 'on' for printing | 1235 | flags : '=p' means the line is turned 'on' for printing |
| 1227 | format : the format used for the debug statement | 1236 | format : the format used for the debug statement |
| 1228 | 1237 | ||
| 1229 | From a live system: | 1238 | From a live system: |
| 1230 | 1239 | ||
| 1231 | nullarbor:~ # cat <debugfs>/dynamic_debug/control | 1240 | nullarbor:~ # cat <debugfs>/dynamic_debug/control |
| 1232 | # filename:lineno [module]function flags format | 1241 | # filename:lineno [module]function flags format |
| 1233 | fs/aio.c:222 [aio]__put_ioctx - "__put_ioctx:\040freeing\040%p\012" | 1242 | fs/aio.c:222 [aio]__put_ioctx =_ "__put_ioctx:\040freeing\040%p\012" |
| 1234 | fs/aio.c:248 [aio]ioctx_alloc - "ENOMEM:\040nr_events\040too\040high\012" | 1243 | fs/aio.c:248 [aio]ioctx_alloc =_ "ENOMEM:\040nr_events\040too\040high\012" |
| 1235 | fs/aio.c:1770 [aio]sys_io_cancel - "calling\040cancel\012" | 1244 | fs/aio.c:1770 [aio]sys_io_cancel =_ "calling\040cancel\012" |
| 1236 | 1245 | ||
| 1237 | Example usage: | 1246 | Example usage: |
| 1238 | 1247 | ||
diff --git a/lib/Makefile b/lib/Makefile index 18515f0267c4..74290c9e2864 100644 --- a/lib/Makefile +++ b/lib/Makefile | |||
| @@ -123,6 +123,8 @@ obj-$(CONFIG_SIGNATURE) += digsig.o | |||
| 123 | 123 | ||
| 124 | obj-$(CONFIG_CLZ_TAB) += clz_tab.o | 124 | obj-$(CONFIG_CLZ_TAB) += clz_tab.o |
| 125 | 125 | ||
| 126 | obj-$(CONFIG_DDR) += jedec_ddr_data.o | ||
| 127 | |||
| 126 | hostprogs-y := gen_crc32table | 128 | hostprogs-y := gen_crc32table |
| 127 | clean-files := crc32table.h | 129 | clean-files := crc32table.h |
| 128 | 130 | ||
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index 310c753cf83e..7ca29a0a3019 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c | |||
| @@ -107,20 +107,22 @@ static char *ddebug_describe_flags(struct _ddebug *dp, char *buf, | |||
| 107 | return buf; | 107 | return buf; |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | #define vpr_info_dq(q, msg) \ | 110 | #define vpr_info(fmt, ...) \ |
| 111 | do { \ | 111 | if (verbose) do { pr_info(fmt, ##__VA_ARGS__); } while (0) |
| 112 | if (verbose) \ | 112 | |
| 113 | /* trim last char off format print */ \ | 113 | #define vpr_info_dq(q, msg) \ |
| 114 | pr_info("%s: func=\"%s\" file=\"%s\" " \ | 114 | do { \ |
| 115 | "module=\"%s\" format=\"%.*s\" " \ | 115 | /* trim last char off format print */ \ |
| 116 | "lineno=%u-%u", \ | 116 | vpr_info("%s: func=\"%s\" file=\"%s\" " \ |
| 117 | msg, \ | 117 | "module=\"%s\" format=\"%.*s\" " \ |
| 118 | q->function ? q->function : "", \ | 118 | "lineno=%u-%u", \ |
| 119 | q->filename ? q->filename : "", \ | 119 | msg, \ |
| 120 | q->module ? q->module : "", \ | 120 | q->function ? q->function : "", \ |
| 121 | (int)(q->format ? strlen(q->format) - 1 : 0), \ | 121 | q->filename ? q->filename : "", \ |
| 122 | q->format ? q->format : "", \ | 122 | q->module ? q->module : "", \ |
| 123 | q->first_lineno, q->last_lineno); \ | 123 | (int)(q->format ? strlen(q->format) - 1 : 0), \ |
| 124 | q->format ? q->format : "", \ | ||
| 125 | q->first_lineno, q->last_lineno); \ | ||
| 124 | } while (0) | 126 | } while (0) |
| 125 | 127 | ||
| 126 | /* | 128 | /* |
| @@ -180,12 +182,11 @@ static int ddebug_change(const struct ddebug_query *query, | |||
| 180 | if (newflags == dp->flags) | 182 | if (newflags == dp->flags) |
| 181 | continue; | 183 | continue; |
| 182 | dp->flags = newflags; | 184 | dp->flags = newflags; |
| 183 | if (verbose) | 185 | vpr_info("changed %s:%d [%s]%s =%s\n", |
| 184 | pr_info("changed %s:%d [%s]%s =%s\n", | 186 | trim_prefix(dp->filename), dp->lineno, |
| 185 | trim_prefix(dp->filename), dp->lineno, | 187 | dt->mod_name, dp->function, |
| 186 | dt->mod_name, dp->function, | 188 | ddebug_describe_flags(dp, flagbuf, |
| 187 | ddebug_describe_flags(dp, flagbuf, | 189 | sizeof(flagbuf))); |
| 188 | sizeof(flagbuf))); | ||
| 189 | } | 190 | } |
| 190 | } | 191 | } |
| 191 | mutex_unlock(&ddebug_lock); | 192 | mutex_unlock(&ddebug_lock); |
| @@ -337,7 +338,7 @@ static int check_set(const char **dest, char *src, char *name) | |||
| 337 | * Returns 0 on success, <0 on error. | 338 | * Returns 0 on success, <0 on error. |
| 338 | */ | 339 | */ |
| 339 | static int ddebug_parse_query(char *words[], int nwords, | 340 | static int ddebug_parse_query(char *words[], int nwords, |
| 340 | struct ddebug_query *query) | 341 | struct ddebug_query *query, const char *modname) |
| 341 | { | 342 | { |
| 342 | unsigned int i; | 343 | unsigned int i; |
| 343 | int rc; | 344 | int rc; |
| @@ -347,6 +348,10 @@ static int ddebug_parse_query(char *words[], int nwords, | |||
| 347 | return -EINVAL; | 348 | return -EINVAL; |
| 348 | memset(query, 0, sizeof(*query)); | 349 | memset(query, 0, sizeof(*query)); |
| 349 | 350 | ||
| 351 | if (modname) | ||
| 352 | /* support $modname.dyndbg=<multiple queries> */ | ||
| 353 | query->module = modname; | ||
| 354 | |||
| 350 | for (i = 0 ; i < nwords ; i += 2) { | 355 | for (i = 0 ; i < nwords ; i += 2) { |
| 351 | if (!strcmp(words[i], "func")) | 356 | if (!strcmp(words[i], "func")) |
| 352 | rc = check_set(&query->function, words[i+1], "func"); | 357 | rc = check_set(&query->function, words[i+1], "func"); |
| @@ -410,8 +415,7 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp, | |||
| 410 | default: | 415 | default: |
| 411 | return -EINVAL; | 416 | return -EINVAL; |
| 412 | } | 417 | } |
| 413 | if (verbose) | 418 | vpr_info("op='%c'\n", op); |
| 414 | pr_info("op='%c'\n", op); | ||
| 415 | 419 | ||
| 416 | for ( ; *str ; ++str) { | 420 | for ( ; *str ; ++str) { |
| 417 | for (i = ARRAY_SIZE(opt_array) - 1; i >= 0; i--) { | 421 | for (i = ARRAY_SIZE(opt_array) - 1; i >= 0; i--) { |
| @@ -423,8 +427,7 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp, | |||
| 423 | if (i < 0) | 427 | if (i < 0) |
| 424 | return -EINVAL; | 428 | return -EINVAL; |
| 425 | } | 429 | } |
| 426 | if (verbose) | 430 | vpr_info("flags=0x%x\n", flags); |
| 427 | pr_info("flags=0x%x\n", flags); | ||
| 428 | 431 | ||
| 429 | /* calculate final *flagsp, *maskp according to mask and op */ | 432 | /* calculate final *flagsp, *maskp according to mask and op */ |
| 430 | switch (op) { | 433 | switch (op) { |
| @@ -441,12 +444,11 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp, | |||
| 441 | *flagsp = 0; | 444 | *flagsp = 0; |
| 442 | break; | 445 | break; |
| 443 | } | 446 | } |
| 444 | if (verbose) | 447 | vpr_info("*flagsp=0x%x *maskp=0x%x\n", *flagsp, *maskp); |
| 445 | pr_info("*flagsp=0x%x *maskp=0x%x\n", *flagsp, *maskp); | ||
| 446 | return 0; | 448 | return 0; |
| 447 | } | 449 | } |
| 448 | 450 | ||
| 449 | static int ddebug_exec_query(char *query_string) | 451 | static int ddebug_exec_query(char *query_string, const char *modname) |
| 450 | { | 452 | { |
| 451 | unsigned int flags = 0, mask = 0; | 453 | unsigned int flags = 0, mask = 0; |
| 452 | struct ddebug_query query; | 454 | struct ddebug_query query; |
| @@ -457,7 +459,7 @@ static int ddebug_exec_query(char *query_string) | |||
| 457 | nwords = ddebug_tokenize(query_string, words, MAXWORDS); | 459 | nwords = ddebug_tokenize(query_string, words, MAXWORDS); |
| 458 | if (nwords <= 0) | 460 | if (nwords <= 0) |
| 459 | return -EINVAL; | 461 | return -EINVAL; |
| 460 | if (ddebug_parse_query(words, nwords-1, &query)) | 462 | if (ddebug_parse_query(words, nwords-1, &query, modname)) |
| 461 | return -EINVAL; | 463 | return -EINVAL; |
| 462 | if (ddebug_parse_flags(words[nwords-1], &flags, &mask)) | 464 | if (ddebug_parse_flags(words[nwords-1], &flags, &mask)) |
| 463 | return -EINVAL; | 465 | return -EINVAL; |
| @@ -473,7 +475,7 @@ static int ddebug_exec_query(char *query_string) | |||
| 473 | last error or number of matching callsites. Module name is either | 475 | last error or number of matching callsites. Module name is either |
| 474 | in param (for boot arg) or perhaps in query string. | 476 | in param (for boot arg) or perhaps in query string. |
| 475 | */ | 477 | */ |
| 476 | static int ddebug_exec_queries(char *query) | 478 | static int ddebug_exec_queries(char *query, const char *modname) |
| 477 | { | 479 | { |
| 478 | char *split; | 480 | char *split; |
| 479 | int i, errs = 0, exitcode = 0, rc, nfound = 0; | 481 | int i, errs = 0, exitcode = 0, rc, nfound = 0; |
| @@ -487,10 +489,9 @@ static int ddebug_exec_queries(char *query) | |||
| 487 | if (!query || !*query || *query == '#') | 489 | if (!query || !*query || *query == '#') |
| 488 | continue; | 490 | continue; |
| 489 | 491 | ||
| 490 | if (verbose) | 492 | vpr_info("query %d: \"%s\"\n", i, query); |
| 491 | pr_info("query %d: \"%s\"\n", i, query); | ||
| 492 | 493 | ||
| 493 | rc = ddebug_exec_query(query); | 494 | rc = ddebug_exec_query(query, modname); |
| 494 | if (rc < 0) { | 495 | if (rc < 0) { |
| 495 | errs++; | 496 | errs++; |
| 496 | exitcode = rc; | 497 | exitcode = rc; |
| @@ -498,7 +499,7 @@ static int ddebug_exec_queries(char *query) | |||
| 498 | nfound += rc; | 499 | nfound += rc; |
| 499 | i++; | 500 | i++; |
| 500 | } | 501 | } |
| 501 | pr_info("processed %d queries, with %d matches, %d errs\n", | 502 | vpr_info("processed %d queries, with %d matches, %d errs\n", |
| 502 | i, nfound, errs); | 503 | i, nfound, errs); |
| 503 | 504 | ||
| 504 | if (exitcode) | 505 | if (exitcode) |
| @@ -653,10 +654,9 @@ static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf, | |||
| 653 | return -EFAULT; | 654 | return -EFAULT; |
| 654 | } | 655 | } |
| 655 | tmpbuf[len] = '\0'; | 656 | tmpbuf[len] = '\0'; |
| 656 | if (verbose) | 657 | vpr_info("read %d bytes from userspace\n", (int)len); |
| 657 | pr_info("read %d bytes from userspace\n", (int)len); | ||
| 658 | 658 | ||
| 659 | ret = ddebug_exec_queries(tmpbuf); | 659 | ret = ddebug_exec_queries(tmpbuf, NULL); |
| 660 | kfree(tmpbuf); | 660 | kfree(tmpbuf); |
| 661 | if (ret < 0) | 661 | if (ret < 0) |
| 662 | return ret; | 662 | return ret; |
| @@ -717,8 +717,7 @@ static void *ddebug_proc_start(struct seq_file *m, loff_t *pos) | |||
| 717 | struct _ddebug *dp; | 717 | struct _ddebug *dp; |
| 718 | int n = *pos; | 718 | int n = *pos; |
| 719 | 719 | ||
| 720 | if (verbose) | 720 | vpr_info("called m=%p *pos=%lld\n", m, (unsigned long long)*pos); |
| 721 | pr_info("called m=%p *pos=%lld\n", m, (unsigned long long)*pos); | ||
| 722 | 721 | ||
| 723 | mutex_lock(&ddebug_lock); | 722 | mutex_lock(&ddebug_lock); |
| 724 | 723 | ||
| @@ -742,9 +741,8 @@ static void *ddebug_proc_next(struct seq_file *m, void *p, loff_t *pos) | |||
| 742 | struct ddebug_iter *iter = m->private; | 741 | struct ddebug_iter *iter = m->private; |
| 743 | struct _ddebug *dp; | 742 | struct _ddebug *dp; |
| 744 | 743 | ||
| 745 | if (verbose) | 744 | vpr_info("called m=%p p=%p *pos=%lld\n", |
| 746 | pr_info("called m=%p p=%p *pos=%lld\n", | 745 | m, p, (unsigned long long)*pos); |
| 747 | m, p, (unsigned long long)*pos); | ||
| 748 | 746 | ||
| 749 | if (p == SEQ_START_TOKEN) | 747 | if (p == SEQ_START_TOKEN) |
| 750 | dp = ddebug_iter_first(iter); | 748 | dp = ddebug_iter_first(iter); |
| @@ -766,8 +764,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p) | |||
| 766 | struct _ddebug *dp = p; | 764 | struct _ddebug *dp = p; |
| 767 | char flagsbuf[10]; | 765 | char flagsbuf[10]; |
| 768 | 766 | ||
| 769 | if (verbose) | 767 | vpr_info("called m=%p p=%p\n", m, p); |
| 770 | pr_info("called m=%p p=%p\n", m, p); | ||
| 771 | 768 | ||
| 772 | if (p == SEQ_START_TOKEN) { | 769 | if (p == SEQ_START_TOKEN) { |
| 773 | seq_puts(m, | 770 | seq_puts(m, |
| @@ -791,8 +788,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p) | |||
| 791 | */ | 788 | */ |
| 792 | static void ddebug_proc_stop(struct seq_file *m, void *p) | 789 | static void ddebug_proc_stop(struct seq_file *m, void *p) |
| 793 | { | 790 | { |
| 794 | if (verbose) | 791 | vpr_info("called m=%p p=%p\n", m, p); |
| 795 | pr_info("called m=%p p=%p\n", m, p); | ||
| 796 | mutex_unlock(&ddebug_lock); | 792 | mutex_unlock(&ddebug_lock); |
| 797 | } | 793 | } |
| 798 | 794 | ||
| @@ -815,8 +811,7 @@ static int ddebug_proc_open(struct inode *inode, struct file *file) | |||
| 815 | struct ddebug_iter *iter; | 811 | struct ddebug_iter *iter; |
| 816 | int err; | 812 | int err; |
| 817 | 813 | ||
| 818 | if (verbose) | 814 | vpr_info("called\n"); |
| 819 | pr_info("called\n"); | ||
| 820 | 815 | ||
| 821 | iter = kzalloc(sizeof(*iter), GFP_KERNEL); | 816 | iter = kzalloc(sizeof(*iter), GFP_KERNEL); |
| 822 | if (iter == NULL) | 817 | if (iter == NULL) |
| @@ -866,12 +861,51 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n, | |||
| 866 | list_add_tail(&dt->link, &ddebug_tables); | 861 | list_add_tail(&dt->link, &ddebug_tables); |
| 867 | mutex_unlock(&ddebug_lock); | 862 | mutex_unlock(&ddebug_lock); |
| 868 | 863 | ||
| 869 | if (verbose) | 864 | vpr_info("%u debug prints in module %s\n", n, dt->mod_name); |
| 870 | pr_info("%u debug prints in module %s\n", n, dt->mod_name); | ||
| 871 | return 0; | 865 | return 0; |
| 872 | } | 866 | } |
| 873 | EXPORT_SYMBOL_GPL(ddebug_add_module); | 867 | EXPORT_SYMBOL_GPL(ddebug_add_module); |
| 874 | 868 | ||
| 869 | /* helper for ddebug_dyndbg_(boot|module)_param_cb */ | ||
| 870 | static int ddebug_dyndbg_param_cb(char *param, char *val, | ||
| 871 | const char *modname, int on_err) | ||
| 872 | { | ||
| 873 | char *sep; | ||
| 874 | |||
| 875 | sep = strchr(param, '.'); | ||
| 876 | if (sep) { | ||
| 877 | /* needed only for ddebug_dyndbg_boot_param_cb */ | ||
| 878 | *sep = '\0'; | ||
| 879 | modname = param; | ||
| 880 | param = sep + 1; | ||
| 881 | } | ||
| 882 | if (strcmp(param, "dyndbg")) | ||
| 883 | return on_err; /* determined by caller */ | ||
| 884 | |||
| 885 | ddebug_exec_queries((val ? val : "+p"), modname); | ||
| 886 | |||
| 887 | return 0; /* query failure shouldnt stop module load */ | ||
| 888 | } | ||
| 889 | |||
| 890 | /* handle both dyndbg and $module.dyndbg params at boot */ | ||
| 891 | static int ddebug_dyndbg_boot_param_cb(char *param, char *val, | ||
| 892 | const char *unused) | ||
| 893 | { | ||
| 894 | vpr_info("%s=\"%s\"\n", param, val); | ||
| 895 | return ddebug_dyndbg_param_cb(param, val, NULL, 0); | ||
| 896 | } | ||
| 897 | |||
| 898 | /* | ||
| 899 | * modprobe foo finds foo.params in boot-args, strips "foo.", and | ||
| 900 | * passes them to load_module(). This callback gets unknown params, | ||
| 901 | * processes dyndbg params, rejects others. | ||
| 902 | */ | ||
| 903 | int ddebug_dyndbg_module_param_cb(char *param, char *val, const char *module) | ||
| 904 | { | ||
| 905 | vpr_info("module: %s %s=\"%s\"\n", module, param, val); | ||
| 906 | return ddebug_dyndbg_param_cb(param, val, module, -ENOENT); | ||
| 907 | } | ||
| 908 | |||
| 875 | static void ddebug_table_free(struct ddebug_table *dt) | 909 | static void ddebug_table_free(struct ddebug_table *dt) |
| 876 | { | 910 | { |
| 877 | list_del_init(&dt->link); | 911 | list_del_init(&dt->link); |
| @@ -888,8 +922,7 @@ int ddebug_remove_module(const char *mod_name) | |||
| 888 | struct ddebug_table *dt, *nextdt; | 922 | struct ddebug_table *dt, *nextdt; |
| 889 | int ret = -ENOENT; | 923 | int ret = -ENOENT; |
| 890 | 924 | ||
| 891 | if (verbose) | 925 | vpr_info("removing module \"%s\"\n", mod_name); |
| 892 | pr_info("removing module \"%s\"\n", mod_name); | ||
| 893 | 926 | ||
| 894 | mutex_lock(&ddebug_lock); | 927 | mutex_lock(&ddebug_lock); |
| 895 | list_for_each_entry_safe(dt, nextdt, &ddebug_tables, link) { | 928 | list_for_each_entry_safe(dt, nextdt, &ddebug_tables, link) { |
| @@ -940,8 +973,10 @@ static int __init dynamic_debug_init(void) | |||
| 940 | { | 973 | { |
| 941 | struct _ddebug *iter, *iter_start; | 974 | struct _ddebug *iter, *iter_start; |
| 942 | const char *modname = NULL; | 975 | const char *modname = NULL; |
| 976 | char *cmdline; | ||
| 943 | int ret = 0; | 977 | int ret = 0; |
| 944 | int n = 0; | 978 | int n = 0, entries = 0, modct = 0; |
| 979 | int verbose_bytes = 0; | ||
| 945 | 980 | ||
| 946 | if (__start___verbose == __stop___verbose) { | 981 | if (__start___verbose == __stop___verbose) { |
| 947 | pr_warn("_ddebug table is empty in a " | 982 | pr_warn("_ddebug table is empty in a " |
| @@ -952,10 +987,15 @@ static int __init dynamic_debug_init(void) | |||
| 952 | modname = iter->modname; | 987 | modname = iter->modname; |
| 953 | iter_start = iter; | 988 | iter_start = iter; |
| 954 | for (; iter < __stop___verbose; iter++) { | 989 | for (; iter < __stop___verbose; iter++) { |
| 990 | entries++; | ||
| 991 | verbose_bytes += strlen(iter->modname) + strlen(iter->function) | ||
| 992 | + strlen(iter->filename) + strlen(iter->format); | ||
| 993 | |||
| 955 | if (strcmp(modname, iter->modname)) { | 994 | if (strcmp(modname, iter->modname)) { |
| 995 | modct++; | ||
| 956 | ret = ddebug_add_module(iter_start, n, modname); | 996 | ret = ddebug_add_module(iter_start, n, modname); |
| 957 | if (ret) | 997 | if (ret) |
| 958 | goto out_free; | 998 | goto out_err; |
| 959 | n = 0; | 999 | n = 0; |
| 960 | modname = iter->modname; | 1000 | modname = iter->modname; |
| 961 | iter_start = iter; | 1001 | iter_start = iter; |
| @@ -964,29 +1004,45 @@ static int __init dynamic_debug_init(void) | |||
| 964 | } | 1004 | } |
| 965 | ret = ddebug_add_module(iter_start, n, modname); | 1005 | ret = ddebug_add_module(iter_start, n, modname); |
| 966 | if (ret) | 1006 | if (ret) |
| 967 | goto out_free; | 1007 | goto out_err; |
| 1008 | |||
| 1009 | ddebug_init_success = 1; | ||
| 1010 | vpr_info("%d modules, %d entries and %d bytes in ddebug tables," | ||
| 1011 | " %d bytes in (readonly) verbose section\n", | ||
| 1012 | modct, entries, (int)( modct * sizeof(struct ddebug_table)), | ||
| 1013 | verbose_bytes + (int)(__stop___verbose - __start___verbose)); | ||
| 968 | 1014 | ||
| 969 | /* ddebug_query boot param got passed -> set it up */ | 1015 | /* apply ddebug_query boot param, dont unload tables on err */ |
| 970 | if (ddebug_setup_string[0] != '\0') { | 1016 | if (ddebug_setup_string[0] != '\0') { |
| 971 | ret = ddebug_exec_queries(ddebug_setup_string); | 1017 | pr_warn("ddebug_query param name is deprecated," |
| 1018 | " change it to dyndbg\n"); | ||
| 1019 | ret = ddebug_exec_queries(ddebug_setup_string, NULL); | ||
| 972 | if (ret < 0) | 1020 | if (ret < 0) |
| 973 | pr_warn("Invalid ddebug boot param %s", | 1021 | pr_warn("Invalid ddebug boot param %s", |
| 974 | ddebug_setup_string); | 1022 | ddebug_setup_string); |
| 975 | else | 1023 | else |
| 976 | pr_info("%d changes by ddebug_query\n", ret); | 1024 | pr_info("%d changes by ddebug_query\n", ret); |
| 977 | |||
| 978 | /* keep tables even on ddebug_query parse error */ | ||
| 979 | ret = 0; | ||
| 980 | } | 1025 | } |
| 1026 | /* now that ddebug tables are loaded, process all boot args | ||
| 1027 | * again to find and activate queries given in dyndbg params. | ||
| 1028 | * While this has already been done for known boot params, it | ||
| 1029 | * ignored the unknown ones (dyndbg in particular). Reusing | ||
| 1030 | * parse_args avoids ad-hoc parsing. This will also attempt | ||
| 1031 | * to activate queries for not-yet-loaded modules, which is | ||
| 1032 | * slightly noisy if verbose, but harmless. | ||
| 1033 | */ | ||
| 1034 | cmdline = kstrdup(saved_command_line, GFP_KERNEL); | ||
| 1035 | parse_args("dyndbg params", cmdline, NULL, | ||
| 1036 | 0, 0, 0, &ddebug_dyndbg_boot_param_cb); | ||
| 1037 | kfree(cmdline); | ||
| 1038 | return 0; | ||
| 981 | 1039 | ||
| 982 | out_free: | 1040 | out_err: |
| 983 | if (ret) | 1041 | ddebug_remove_all_tables(); |
| 984 | ddebug_remove_all_tables(); | ||
| 985 | else | ||
| 986 | ddebug_init_success = 1; | ||
| 987 | return 0; | 1042 | return 0; |
| 988 | } | 1043 | } |
| 989 | /* Allow early initialization for boot messages via boot param */ | 1044 | /* Allow early initialization for boot messages via boot param */ |
| 990 | arch_initcall(dynamic_debug_init); | 1045 | early_initcall(dynamic_debug_init); |
| 1046 | |||
| 991 | /* Debugfs setup must be done later */ | 1047 | /* Debugfs setup must be done later */ |
| 992 | module_init(dynamic_debug_init_debugfs); | 1048 | fs_initcall(dynamic_debug_init_debugfs); |
diff --git a/lib/jedec_ddr_data.c b/lib/jedec_ddr_data.c new file mode 100644 index 000000000000..6d2cbf1d567f --- /dev/null +++ b/lib/jedec_ddr_data.c | |||
| @@ -0,0 +1,135 @@ | |||
| 1 | /* | ||
| 2 | * DDR addressing details and AC timing parameters from JEDEC specs | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Texas Instruments, Inc. | ||
| 5 | * | ||
| 6 | * Aneesh V <aneesh@ti.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <memory/jedec_ddr.h> | ||
| 14 | #include <linux/module.h> | ||
| 15 | |||
| 16 | /* LPDDR2 addressing details from JESD209-2 section 2.4 */ | ||
| 17 | const struct lpddr2_addressing | ||
| 18 | lpddr2_jedec_addressing_table[NUM_DDR_ADDR_TABLE_ENTRIES] = { | ||
| 19 | {B4, T_REFI_15_6, T_RFC_90}, /* 64M */ | ||
| 20 | {B4, T_REFI_15_6, T_RFC_90}, /* 128M */ | ||
| 21 | {B4, T_REFI_7_8, T_RFC_90}, /* 256M */ | ||
| 22 | {B4, T_REFI_7_8, T_RFC_90}, /* 512M */ | ||
| 23 | {B8, T_REFI_7_8, T_RFC_130}, /* 1GS4 */ | ||
| 24 | {B8, T_REFI_3_9, T_RFC_130}, /* 2GS4 */ | ||
| 25 | {B8, T_REFI_3_9, T_RFC_130}, /* 4G */ | ||
| 26 | {B8, T_REFI_3_9, T_RFC_210}, /* 8G */ | ||
| 27 | {B4, T_REFI_7_8, T_RFC_130}, /* 1GS2 */ | ||
| 28 | {B4, T_REFI_3_9, T_RFC_130}, /* 2GS2 */ | ||
| 29 | }; | ||
| 30 | EXPORT_SYMBOL_GPL(lpddr2_jedec_addressing_table); | ||
| 31 | |||
| 32 | /* LPDDR2 AC timing parameters from JESD209-2 section 12 */ | ||
| 33 | const struct lpddr2_timings | ||
| 34 | lpddr2_jedec_timings[NUM_DDR_TIMING_TABLE_ENTRIES] = { | ||
| 35 | /* Speed bin 400(200 MHz) */ | ||
| 36 | [0] = { | ||
| 37 | .max_freq = 200000000, | ||
| 38 | .min_freq = 10000000, | ||
| 39 | .tRPab = 21000, | ||
| 40 | .tRCD = 18000, | ||
| 41 | .tWR = 15000, | ||
| 42 | .tRAS_min = 42000, | ||
| 43 | .tRRD = 10000, | ||
| 44 | .tWTR = 10000, | ||
| 45 | .tXP = 7500, | ||
| 46 | .tRTP = 7500, | ||
| 47 | .tCKESR = 15000, | ||
| 48 | .tDQSCK_max = 5500, | ||
| 49 | .tFAW = 50000, | ||
| 50 | .tZQCS = 90000, | ||
| 51 | .tZQCL = 360000, | ||
| 52 | .tZQinit = 1000000, | ||
| 53 | .tRAS_max_ns = 70000, | ||
| 54 | .tDQSCK_max_derated = 6000, | ||
| 55 | }, | ||
| 56 | /* Speed bin 533(266 MHz) */ | ||
| 57 | [1] = { | ||
| 58 | .max_freq = 266666666, | ||
| 59 | .min_freq = 10000000, | ||
| 60 | .tRPab = 21000, | ||
| 61 | .tRCD = 18000, | ||
| 62 | .tWR = 15000, | ||
| 63 | .tRAS_min = 42000, | ||
| 64 | .tRRD = 10000, | ||
| 65 | .tWTR = 7500, | ||
| 66 | .tXP = 7500, | ||
| 67 | .tRTP = 7500, | ||
| 68 | .tCKESR = 15000, | ||
| 69 | .tDQSCK_max = 5500, | ||
| 70 | .tFAW = 50000, | ||
| 71 | .tZQCS = 90000, | ||
| 72 | .tZQCL = 360000, | ||
| 73 | .tZQinit = 1000000, | ||
| 74 | .tRAS_max_ns = 70000, | ||
| 75 | .tDQSCK_max_derated = 6000, | ||
| 76 | }, | ||
| 77 | /* Speed bin 800(400 MHz) */ | ||
| 78 | [2] = { | ||
| 79 | .max_freq = 400000000, | ||
| 80 | .min_freq = 10000000, | ||
| 81 | .tRPab = 21000, | ||
| 82 | .tRCD = 18000, | ||
| 83 | .tWR = 15000, | ||
| 84 | .tRAS_min = 42000, | ||
| 85 | .tRRD = 10000, | ||
| 86 | .tWTR = 7500, | ||
| 87 | .tXP = 7500, | ||
| 88 | .tRTP = 7500, | ||
| 89 | .tCKESR = 15000, | ||
| 90 | .tDQSCK_max = 5500, | ||
| 91 | .tFAW = 50000, | ||
| 92 | .tZQCS = 90000, | ||
| 93 | .tZQCL = 360000, | ||
| 94 | .tZQinit = 1000000, | ||
| 95 | .tRAS_max_ns = 70000, | ||
| 96 | .tDQSCK_max_derated = 6000, | ||
| 97 | }, | ||
| 98 | /* Speed bin 1066(533 MHz) */ | ||
| 99 | [3] = { | ||
| 100 | .max_freq = 533333333, | ||
| 101 | .min_freq = 10000000, | ||
| 102 | .tRPab = 21000, | ||
| 103 | .tRCD = 18000, | ||
| 104 | .tWR = 15000, | ||
| 105 | .tRAS_min = 42000, | ||
| 106 | .tRRD = 10000, | ||
| 107 | .tWTR = 7500, | ||
| 108 | .tXP = 7500, | ||
| 109 | .tRTP = 7500, | ||
| 110 | .tCKESR = 15000, | ||
| 111 | .tDQSCK_max = 5500, | ||
| 112 | .tFAW = 50000, | ||
| 113 | .tZQCS = 90000, | ||
| 114 | .tZQCL = 360000, | ||
| 115 | .tZQinit = 1000000, | ||
| 116 | .tRAS_max_ns = 70000, | ||
| 117 | .tDQSCK_max_derated = 5620, | ||
| 118 | }, | ||
| 119 | }; | ||
| 120 | EXPORT_SYMBOL_GPL(lpddr2_jedec_timings); | ||
| 121 | |||
| 122 | const struct lpddr2_min_tck lpddr2_jedec_min_tck = { | ||
| 123 | .tRPab = 3, | ||
| 124 | .tRCD = 3, | ||
| 125 | .tWR = 3, | ||
| 126 | .tRASmin = 3, | ||
| 127 | .tRRD = 2, | ||
| 128 | .tWTR = 2, | ||
| 129 | .tXP = 2, | ||
| 130 | .tRTP = 2, | ||
| 131 | .tCKE = 3, | ||
| 132 | .tCKESR = 3, | ||
| 133 | .tFAW = 8 | ||
| 134 | }; | ||
| 135 | EXPORT_SYMBOL_GPL(lpddr2_jedec_min_tck); | ||
diff --git a/lib/kobject.c b/lib/kobject.c index aeefa8bc8b1c..e07ee1fcd6f1 100644 --- a/lib/kobject.c +++ b/lib/kobject.c | |||
| @@ -47,13 +47,11 @@ static int populate_dir(struct kobject *kobj) | |||
| 47 | static int create_dir(struct kobject *kobj) | 47 | static int create_dir(struct kobject *kobj) |
| 48 | { | 48 | { |
| 49 | int error = 0; | 49 | int error = 0; |
| 50 | if (kobject_name(kobj)) { | 50 | error = sysfs_create_dir(kobj); |
| 51 | error = sysfs_create_dir(kobj); | 51 | if (!error) { |
| 52 | if (!error) { | 52 | error = populate_dir(kobj); |
| 53 | error = populate_dir(kobj); | 53 | if (error) |
| 54 | if (error) | 54 | sysfs_remove_dir(kobj); |
| 55 | sysfs_remove_dir(kobj); | ||
| 56 | } | ||
| 57 | } | 55 | } |
| 58 | return error; | 56 | return error; |
| 59 | } | 57 | } |
| @@ -634,7 +632,7 @@ struct kobject *kobject_create(void) | |||
| 634 | /** | 632 | /** |
| 635 | * kobject_create_and_add - create a struct kobject dynamically and register it with sysfs | 633 | * kobject_create_and_add - create a struct kobject dynamically and register it with sysfs |
| 636 | * | 634 | * |
| 637 | * @name: the name for the kset | 635 | * @name: the name for the kobject |
| 638 | * @parent: the parent kobject of this kobject, if any. | 636 | * @parent: the parent kobject of this kobject, if any. |
| 639 | * | 637 | * |
| 640 | * This function creates a kobject structure dynamically and registers it | 638 | * This function creates a kobject structure dynamically and registers it |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 918330f71dba..9f389e50ed18 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
| @@ -4763,12 +4763,12 @@ void __init free_area_init_nodes(unsigned long *max_zone_pfn) | |||
| 4763 | for (i = 0; i < MAX_NR_ZONES; i++) { | 4763 | for (i = 0; i < MAX_NR_ZONES; i++) { |
| 4764 | if (i == ZONE_MOVABLE) | 4764 | if (i == ZONE_MOVABLE) |
| 4765 | continue; | 4765 | continue; |
| 4766 | printk(" %-8s ", zone_names[i]); | 4766 | printk(KERN_CONT " %-8s ", zone_names[i]); |
| 4767 | if (arch_zone_lowest_possible_pfn[i] == | 4767 | if (arch_zone_lowest_possible_pfn[i] == |
| 4768 | arch_zone_highest_possible_pfn[i]) | 4768 | arch_zone_highest_possible_pfn[i]) |
| 4769 | printk("empty\n"); | 4769 | printk(KERN_CONT "empty\n"); |
| 4770 | else | 4770 | else |
| 4771 | printk("%0#10lx -> %0#10lx\n", | 4771 | printk(KERN_CONT "%0#10lx -> %0#10lx\n", |
| 4772 | arch_zone_lowest_possible_pfn[i], | 4772 | arch_zone_lowest_possible_pfn[i], |
| 4773 | arch_zone_highest_possible_pfn[i]); | 4773 | arch_zone_highest_possible_pfn[i]); |
| 4774 | } | 4774 | } |
