diff options
136 files changed, 7447 insertions, 395 deletions
diff --git a/Documentation/devicetree/bindings/arm/omap/timer.txt b/Documentation/devicetree/bindings/arm/omap/timer.txt index d02e27c764ec..c5730b9e1434 100644 --- a/Documentation/devicetree/bindings/arm/omap/timer.txt +++ b/Documentation/devicetree/bindings/arm/omap/timer.txt | |||
@@ -32,6 +32,18 @@ Optional properties: | |||
32 | - ti,timer-secure: Indicates the timer is reserved on a secure OMAP device | 32 | - ti,timer-secure: Indicates the timer is reserved on a secure OMAP device |
33 | and therefore cannot be used by the kernel. | 33 | and therefore cannot be used by the kernel. |
34 | 34 | ||
35 | The following optional properties are _required_ only during "late attach" of | ||
36 | remote processors, and only for those timers used by those remoteprocs: | ||
37 | |||
38 | - ti,late-attach: Flag to indicate the timer has already been configure by | ||
39 | boot loader. This property is only relevant for initial | ||
40 | boot, so is removed by the driver during the first | ||
41 | probe. | ||
42 | - ti,no-reset-on-init: Flag to let the hwmod layer not reset the timer at init | ||
43 | - ti,no-idle-on-init: Flag to let the hwmod layer not idle and disable the | ||
44 | timer at init | ||
45 | |||
46 | |||
35 | Example: | 47 | Example: |
36 | 48 | ||
37 | timer12: timer@48304000 { | 49 | timer12: timer@48304000 { |
diff --git a/Documentation/devicetree/bindings/chosen.txt b/Documentation/devicetree/bindings/chosen.txt index 6ae9d82d4c37..b5e39af4ddc0 100644 --- a/Documentation/devicetree/bindings/chosen.txt +++ b/Documentation/devicetree/bindings/chosen.txt | |||
@@ -52,3 +52,48 @@ This property is set (currently only on PowerPC, and only needed on | |||
52 | book3e) by some versions of kexec-tools to tell the new kernel that it | 52 | book3e) by some versions of kexec-tools to tell the new kernel that it |
53 | is being booted by kexec, as the booting environment may differ (e.g. | 53 | is being booted by kexec, as the booting environment may differ (e.g. |
54 | a different secondary CPU release mechanism) | 54 | a different secondary CPU release mechanism) |
55 | |||
56 | linux,usable-memory-range | ||
57 | ------------------------- | ||
58 | |||
59 | This property (arm64 only) holds a base address and size, describing a | ||
60 | limited region in which memory may be considered available for use by | ||
61 | the kernel. Memory outside of this range is not available for use. | ||
62 | |||
63 | This property describes a limitation: memory within this range is only | ||
64 | valid when also described through another mechanism that the kernel | ||
65 | would otherwise use to determine available memory (e.g. memory nodes | ||
66 | or the EFI memory map). Valid memory may be sparse within the range. | ||
67 | e.g. | ||
68 | |||
69 | / { | ||
70 | chosen { | ||
71 | linux,usable-memory-range = <0x9 0xf0000000 0x0 0x10000000>; | ||
72 | }; | ||
73 | }; | ||
74 | |||
75 | The main usage is for crash dump kernel to identify its own usable | ||
76 | memory and exclude, at its boot time, any other memory areas that are | ||
77 | part of the panicked kernel's memory. | ||
78 | |||
79 | While this property does not represent a real hardware, the address | ||
80 | and the size are expressed in #address-cells and #size-cells, | ||
81 | respectively, of the root node. | ||
82 | |||
83 | linux,elfcorehdr | ||
84 | ---------------- | ||
85 | |||
86 | This property (currently used only on arm64) holds the memory range, | ||
87 | the address and the size, of the elf core header which mainly describes | ||
88 | the panicked kernel's memory layout as PT_LOAD segments of elf format. | ||
89 | e.g. | ||
90 | |||
91 | / { | ||
92 | chosen { | ||
93 | linux,elfcorehdr = <0x9 0xfffff000 0x0 0x800>; | ||
94 | }; | ||
95 | }; | ||
96 | |||
97 | While this property does not represent a real hardware, the address | ||
98 | and the size are expressed in #address-cells and #size-cells, | ||
99 | respectively, of the root node. | ||
diff --git a/Documentation/devicetree/bindings/hwlock/hwspinlock-user.txt b/Documentation/devicetree/bindings/hwlock/hwspinlock-user.txt new file mode 100644 index 000000000000..0e5ab1e0b952 --- /dev/null +++ b/Documentation/devicetree/bindings/hwlock/hwspinlock-user.txt | |||
@@ -0,0 +1,20 @@ | |||
1 | Hardware spinlock user-space interface | ||
2 | ====================================== | ||
3 | |||
4 | A hwspinlock client that provides ioctls to lock and unlock the | ||
5 | reserved hwlocks. | ||
6 | |||
7 | Required properties: | ||
8 | - compatible: Should be "hwspinlock-user" | ||
9 | - hwlocks: An array of the phandle and hwlock number | ||
10 | specifier tuple | ||
11 | |||
12 | Example: | ||
13 | |||
14 | gatemp { | ||
15 | compatible = "hwspinlock-user"; | ||
16 | hwlocks = <&hwspinlock 0>, | ||
17 | <&hwspinlock 1>, | ||
18 | <&hwspinlock 2>, | ||
19 | <&hwspinlock 3>; | ||
20 | }; | ||
diff --git a/Documentation/devicetree/bindings/iommu/ti,omap-iommu.txt b/Documentation/devicetree/bindings/iommu/ti,omap-iommu.txt index 4bd10dd881b8..407b2570bb72 100644 --- a/Documentation/devicetree/bindings/iommu/ti,omap-iommu.txt +++ b/Documentation/devicetree/bindings/iommu/ti,omap-iommu.txt | |||
@@ -28,6 +28,20 @@ Optional properties: | |||
28 | instance number should be 0 for DSP MDMA MMUs and 1 for | 28 | instance number should be 0 for DSP MDMA MMUs and 1 for |
29 | DSP EDMA MMUs. | 29 | DSP EDMA MMUs. |
30 | 30 | ||
31 | The following optional properties are _required_ only during "late attach": | ||
32 | - ti,late-attach : Flag to indicate IOMMU has already been configured by | ||
33 | bootloader. This property is only relevant for initial | ||
34 | boot, so is removed by the driver during the first | ||
35 | probe. | ||
36 | - ti,late-attach-dma-pool : Flag to indicate that the pagetable has been allocated | ||
37 | from a DMA pool instead of the usual CMA pool for late | ||
38 | attach case. This property is only relevant for initial | ||
39 | boot, so is removed by the driver during the first | ||
40 | probe. | ||
41 | - ti,no-reset-on-init : Flag to let the hwmod layer not reset the IOMMU at init | ||
42 | - ti,no-idle-on-init : Flag to let the hwmod layer not idle and disable IOMMU | ||
43 | at init | ||
44 | |||
31 | Example: | 45 | Example: |
32 | /* OMAP3 ISP MMU */ | 46 | /* OMAP3 ISP MMU */ |
33 | mmu_isp: mmu@480bd400 { | 47 | mmu_isp: mmu@480bd400 { |
diff --git a/Documentation/devicetree/bindings/media/i2c/tvp5158.txt b/Documentation/devicetree/bindings/media/i2c/tvp5158.txt new file mode 100644 index 000000000000..833dbcda1590 --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/tvp5158.txt | |||
@@ -0,0 +1,34 @@ | |||
1 | * Texas Instruments TVP5158 video decoder | ||
2 | |||
3 | The TVP5158 device is high quality, single-chip | ||
4 | digital video decoder that digitizes and decodes all popular baseband analog | ||
5 | video formats into digital video component. The tvp5158 decoder supports | ||
6 | decoding of NTSC, PAL and SECAM composite and S-video. | ||
7 | |||
8 | TVP5158 generates output in BT656 format with embedded sync. | ||
9 | |||
10 | Required Properties : | ||
11 | - compatible : Must be "ti,tvp5158" | ||
12 | |||
13 | Optional Properties : | ||
14 | There are no custom optional properties although the driver supports | ||
15 | standard endpoint properties as documented in | ||
16 | Documentation/devicetree/bindings/media/video-interfaces.txt | ||
17 | |||
18 | Example: | ||
19 | |||
20 | &i2c2 { | ||
21 | ... | ||
22 | ... | ||
23 | tvp5158@5c { | ||
24 | compatible = "ti,tvp5158"; | ||
25 | reg = <0x58>; | ||
26 | |||
27 | port { | ||
28 | tvp_decoder: endpoint { | ||
29 | /* No properties for BT 656 */ | ||
30 | }; | ||
31 | }; | ||
32 | }; | ||
33 | ... | ||
34 | }; | ||
diff --git a/Documentation/devicetree/bindings/remoteproc/omap-remoteproc.txt b/Documentation/devicetree/bindings/remoteproc/omap-remoteproc.txt index 62b01944adb2..c33e4c33ce1c 100644 --- a/Documentation/devicetree/bindings/remoteproc/omap-remoteproc.txt +++ b/Documentation/devicetree/bindings/remoteproc/omap-remoteproc.txt | |||
@@ -120,6 +120,25 @@ The following are the optional properties: | |||
120 | remoteprocs, and should contain the address containing | 120 | remoteprocs, and should contain the address containing |
121 | the module standby status. | 121 | the module standby status. |
122 | 122 | ||
123 | Required properties when doing "late attach": | ||
124 | --------------------------------------------- | ||
125 | The following three properties are required to support "late attach" (external | ||
126 | entity has already booted the remote processor prior to kernel boot) of a | ||
127 | remote processor. These three properties should also be set on all the IOMMU | ||
128 | and timer nodes used by the remote processor. | ||
129 | |||
130 | - ti,late-attach: Flag to Indicate that the remote processor has already | ||
131 | been configured by boot loader. This property is only | ||
132 | relevant for initial boot, so is removed by the driver | ||
133 | during the first probe. | ||
134 | |||
135 | - ti,no-reset-on-init: Flag to let the hwmod layer not reset the remoteproc | ||
136 | device at init. | ||
137 | |||
138 | - ti,no-idle-on-init: Flag to let the hwmod layer not idle and disable the | ||
139 | remoteproc device at init | ||
140 | |||
141 | |||
123 | Example: | 142 | Example: |
124 | -------- | 143 | -------- |
125 | 144 | ||
diff --git a/Documentation/devicetree/bindings/sound/codecs.txt b/Documentation/devicetree/bindings/sound/codecs.txt new file mode 100644 index 000000000000..8e6630d73fee --- /dev/null +++ b/Documentation/devicetree/bindings/sound/codecs.txt | |||
@@ -0,0 +1,7 @@ | |||
1 | Codecs: | ||
2 | |||
3 | Generic properties for any audio codec handled directly by ASoC core. | ||
4 | |||
5 | Optional properties: | ||
6 | - name-prefix : Name prefix to avoid kcontrol name collisions | ||
7 | in cards with multiple instances of the same codec | ||
diff --git a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt index 46bc9829c71a..00107789a6dd 100644 --- a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt +++ b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt | |||
@@ -39,6 +39,8 @@ Optional properties: | |||
39 | please refer to pinctrl-bindings.txt | 39 | please refer to pinctrl-bindings.txt |
40 | - fck_parent : Should contain a valid clock name which will be used as parent | 40 | - fck_parent : Should contain a valid clock name which will be used as parent |
41 | for the McASP fck | 41 | for the McASP fck |
42 | - shared-dai : CPU DAI is shared (typically shared with DSP). McASP will not be | ||
43 | power managed at runtime. | ||
42 | 44 | ||
43 | Example: | 45 | Example: |
44 | 46 | ||
diff --git a/Documentation/devicetree/bindings/video/fpd3-serdes.txt b/Documentation/devicetree/bindings/video/fpd3-serdes.txt new file mode 100644 index 000000000000..afa56806f7a5 --- /dev/null +++ b/Documentation/devicetree/bindings/video/fpd3-serdes.txt | |||
@@ -0,0 +1,134 @@ | |||
1 | Texas instruments video serializer de serializer | ||
2 | ================================================ | ||
3 | |||
4 | See Documentation/video-serdes.txt for generic information about | ||
5 | video serializer / de serializers. | ||
6 | |||
7 | FPDlink3 video serdes devices are I2C slave devices. They are always | ||
8 | used in pairs where one device is connected to the CPU/SoC which is | ||
9 | called local device and the other one is called remote device. | ||
10 | |||
11 | FPDlink3 video serdes devices have some gpios which can be controlled | ||
12 | over I2C. Also, the FPDlink supports gpio forwarding. Which means that | ||
13 | the remote device can copy the gpio values from it's remote device. | ||
14 | |||
15 | Also, each of the remote device is an I2C master itself, so it can | ||
16 | interface some I2C slaves at remote end. For e.g, a backlight LCD chip | ||
17 | connected to the de serializer or the camera connected to a serializer. | ||
18 | So these slaves can be accessed from local devices via I2C aliases. | ||
19 | |||
20 | A pair of serializer/deserializer can be used for tunneling the i2c | ||
21 | transactions over LVDS channel. The one of the device is connected to | ||
22 | the system i2c bus in slave mode and the other one acts as a master | ||
23 | at the remote end. But, the slave device can register dummy aliases | ||
24 | remote master and for each of the remote slaves. | ||
25 | As this is acting like a i2c bridge driver, we need a method for | ||
26 | configuring the address translations. | ||
27 | |||
28 | Required Properties: | ||
29 | |||
30 | - compatible: should be one of the following. | ||
31 | - "ti,ds90ub913aq": For TI FPDlink3 12bit video serializer | ||
32 | - "ti,ds90ub914aq": For TI FPDlink3 12bit video de serializer | ||
33 | - "ti,ds90uh925q": For TI FPDlink3 24bit video serializer | ||
34 | - "ti,ds90uh928q": For TI FPDlink3 24bit video de serializer | ||
35 | - "ti,ds90ub924q": For TI FPDlink3 24bit video de serializer | ||
36 | - "ti,ds90ub921q": For TI FPDlink3 24bit video serializer | ||
37 | |||
38 | - reg: I2C slave address | ||
39 | This would be the alias adress for remote device. The CPU side | ||
40 | ser/des would address the remote device using this address. | ||
41 | |||
42 | Optional Properties: | ||
43 | |||
44 | - gpio-controller: Marks the device node as a gpio controller. | ||
45 | - #gpio-cells: Should be 1. The first cell is the GPIO number. | ||
46 | |||
47 | - ranges: This is the address translation table for mapping i2c devices | ||
48 | on the remote bus to the i2c address(alias) on parent bus. | ||
49 | The first entry in the ranges property has to of the corresponding | ||
50 | remote ser/des device. | ||
51 | For dynamic address mapping, keep the remote slave address as 0x0 | ||
52 | The corresponding alias would be used if the remote slave doesn't | ||
53 | have an address already mapped. | ||
54 | |||
55 | - slave-mode: This property marks the ser/des as remote device. | ||
56 | For a device where 'slave-mode' property is absent, it is considered | ||
57 | as master device and 'ranges' and 'i2c-bus-num' properties are | ||
58 | compulsory. | ||
59 | |||
60 | Example: | ||
61 | |||
62 | Following example demonstrates device node structure for a camera connected | ||
63 | using FPDlink3 ser/des. Here the deserializer and serializer are connected | ||
64 | only via the LVDS link. The camera is connected on the serializer i2c bus. | ||
65 | Here, serializer and camera are not connected to the system i2c bus, but it | ||
66 | can be accessed from the system i2c bus. The deserializer maps each of the | ||
67 | remote slave onto the system i2c bus and acts as a bridge to transfer any | ||
68 | messages addressed to the remote devices. | ||
69 | |||
70 | ======================================= | ||
71 | +-------+ | ||
72 | |I2C bus| | ||
73 | +-------+ | ||
74 | | | ||
75 | |0x60<real> +------------+ | ||
76 | +-----------|Deserializer|0x60 | ||
77 | | +------------+ | ||
78 | | X | ||
79 | | X | ||
80 | | X <LVDS link> | ||
81 | | X | ||
82 | | X | ||
83 | | +----------+ | ||
84 | | | Remote | | ||
85 | | | i2c bus | | ||
86 | | +----------+ | ||
87 | | | | ||
88 | |0x74<alias> | +----------+ | ||
89 | | <- - - - +------|Serializer| 0x58 | ||
90 | | | +----------+ | ||
91 | | | | ||
92 | |0x38<alias> | +---------+ | ||
93 | | <- - - - +------|OV Camera| 0x30 | ||
94 | | | +---------+ | ||
95 | | | ||
96 | | | ||
97 | ======================================= | ||
98 | |||
99 | i2cbus { | ||
100 | lvds_des: deserializer@60 { | ||
101 | compatible = "ti,ds90ub914aq"; | ||
102 | reg = <0x60>; | ||
103 | |||
104 | gpio-controller; | ||
105 | #gpio-cells=1; | ||
106 | |||
107 | i2c-bus-num = <5>; | ||
108 | }; | ||
109 | }; | ||
110 | |||
111 | &lvds_des { | ||
112 | |||
113 | ranges = <0x58 0x74>, | ||
114 | <0x38 0x30>; | ||
115 | |||
116 | lvds_ser: serializer@58 { | ||
117 | compatible = "ti,ds90ub913aq"; | ||
118 | reg = <0x58>; | ||
119 | remote-device = <&lvds_des>; | ||
120 | |||
121 | gpio-controller; | ||
122 | #gpio-cells=1; | ||
123 | |||
124 | slave-mode; | ||
125 | }; | ||
126 | |||
127 | lvds_cam: camera@30 { | ||
128 | compatible = "ov10635" | ||
129 | reg = <0x30>; | ||
130 | |||
131 | gpios = <&lvds_ser 0>; | ||
132 | /* power pin controlled by serializer local gpio */ | ||
133 | }; | ||
134 | }; | ||
diff --git a/Documentation/kdump/kdump.txt b/Documentation/kdump/kdump.txt index bc4bd5a44b88..b6fe6a885bf8 100644 --- a/Documentation/kdump/kdump.txt +++ b/Documentation/kdump/kdump.txt | |||
@@ -18,7 +18,7 @@ memory image to a dump file on the local disk, or across the network to | |||
18 | a remote system. | 18 | a remote system. |
19 | 19 | ||
20 | Kdump and kexec are currently supported on the x86, x86_64, ppc64, ia64, | 20 | Kdump and kexec are currently supported on the x86, x86_64, ppc64, ia64, |
21 | s390x and arm architectures. | 21 | s390x, arm and arm64 architectures. |
22 | 22 | ||
23 | When the system kernel boots, it reserves a small section of memory for | 23 | When the system kernel boots, it reserves a small section of memory for |
24 | the dump-capture kernel. This ensures that ongoing Direct Memory Access | 24 | the dump-capture kernel. This ensures that ongoing Direct Memory Access |
@@ -249,6 +249,13 @@ Dump-capture kernel config options (Arch Dependent, arm) | |||
249 | 249 | ||
250 | AUTO_ZRELADDR=y | 250 | AUTO_ZRELADDR=y |
251 | 251 | ||
252 | Dump-capture kernel config options (Arch Dependent, arm64) | ||
253 | ---------------------------------------------------------- | ||
254 | |||
255 | - Please note that kvm of the dump-capture kernel will not be enabled | ||
256 | on non-VHE systems even if it is configured. This is because the CPU | ||
257 | will not be reset to EL2 on panic. | ||
258 | |||
252 | Extended crashkernel syntax | 259 | Extended crashkernel syntax |
253 | =========================== | 260 | =========================== |
254 | 261 | ||
@@ -312,6 +319,8 @@ Boot into System Kernel | |||
312 | any space below the alignment point may be overwritten by the dump-capture kernel, | 319 | any space below the alignment point may be overwritten by the dump-capture kernel, |
313 | which means it is possible that the vmcore is not that precise as expected. | 320 | which means it is possible that the vmcore is not that precise as expected. |
314 | 321 | ||
322 | On arm64, use "crashkernel=Y[@X]". Note that the start address of | ||
323 | the kernel, X if explicitly specified, must be aligned to 2MiB (0x200000). | ||
315 | 324 | ||
316 | Load the Dump-capture Kernel | 325 | Load the Dump-capture Kernel |
317 | ============================ | 326 | ============================ |
@@ -334,6 +343,8 @@ For s390x: | |||
334 | - Use image or bzImage | 343 | - Use image or bzImage |
335 | For arm: | 344 | For arm: |
336 | - Use zImage | 345 | - Use zImage |
346 | For arm64: | ||
347 | - Use vmlinux or Image | ||
337 | 348 | ||
338 | If you are using a uncompressed vmlinux image then use following command | 349 | If you are using a uncompressed vmlinux image then use following command |
339 | to load dump-capture kernel. | 350 | to load dump-capture kernel. |
@@ -377,6 +388,9 @@ For s390x: | |||
377 | For arm: | 388 | For arm: |
378 | "1 maxcpus=1 reset_devices" | 389 | "1 maxcpus=1 reset_devices" |
379 | 390 | ||
391 | For arm64: | ||
392 | "1 maxcpus=1 reset_devices" | ||
393 | |||
380 | Notes on loading the dump-capture kernel: | 394 | Notes on loading the dump-capture kernel: |
381 | 395 | ||
382 | * By default, the ELF headers are stored in ELF64 format to support | 396 | * By default, the ELF headers are stored in ELF64 format to support |
diff --git a/Documentation/video-serdes.txt b/Documentation/video-serdes.txt new file mode 100644 index 000000000000..d74da285b518 --- /dev/null +++ b/Documentation/video-serdes.txt | |||
@@ -0,0 +1,42 @@ | |||
1 | Video serializer and de serializer | ||
2 | ================================== | ||
3 | |||
4 | Video serializers and de serializers are the devices which are used to | ||
5 | interface parallel port video imaging or display devices using serial | ||
6 | medium. | ||
7 | |||
8 | Video serializer are used at the transmit side to convert the parallel data | ||
9 | and the control signals to serial data and send it at high frequency | ||
10 | using fewer cables. | ||
11 | Video de serializer are used at the receive side to convert the serial data | ||
12 | into parallel port video and recreate the same control signals. | ||
13 | |||
14 | Typical video serializer/de serializer (serdes) uses data lines as well as | ||
15 | pixel clock, hsync, vsync, etc. | ||
16 | |||
17 | The video serdes devices are controlled via I2C interface and they are always | ||
18 | used in pairs. One end is connected to the video peripheral and other is | ||
19 | connected to the CPU/ SoC. In this way, only one of the device is actually | ||
20 | connected to the I2C bus while other device is controllable remotely. | ||
21 | |||
22 | In case of camera, serializer and camera are remotely connected to the | ||
23 | system and are controllable via deserializer. | ||
24 | First, the deserializer needs to be configured before accessing the | ||
25 | serialzer or the camera. | ||
26 | |||
27 | In case of display, de serializer and display are remotely connected to the | ||
28 | system and are controllable via serializer. | ||
29 | First, the serializer needs to be configured before accessing the | ||
30 | deserializer of the display. | ||
31 | |||
32 | When serdes devices are to be controlled remotely, the device which is | ||
33 | connected to the system registers it's counterpart as an alias. | ||
34 | So that all the accesses done to the alias are reproduced at the remote end. | ||
35 | |||
36 | |||
37 | Linux kernel has driver support for following video devices: | ||
38 | =========================================================== | ||
39 | |||
40 | "drivers/video/serdes/fpd3_serdes.c" supports video (de)serializers. | ||
41 | See Documentation/devicetree/bindings/video/fpd3-serdes.txt | ||
42 | for more information on the devices supported and the device tree bindings | ||
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index e0d7386143b9..8c57745523e4 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile | |||
@@ -494,8 +494,14 @@ dtb-$(CONFIG_SOC_OMAP5) += \ | |||
494 | dtb-$(CONFIG_SOC_DRA7XX) += \ | 494 | dtb-$(CONFIG_SOC_DRA7XX) += \ |
495 | dra7-evm.dtb \ | 495 | dra7-evm.dtb \ |
496 | dra7-evm-lcd-lg.dtb \ | 496 | dra7-evm-lcd-lg.dtb \ |
497 | dra7-evm-fpd-lg.dtb \ | ||
498 | dra7-evm-lcd-lg-late-attach.dtb \ | ||
499 | dra7-evm-lcd-lg-late-attach-no-map.dtb \ | ||
497 | dra7-evm-lcd-osd.dtb \ | 500 | dra7-evm-lcd-osd.dtb \ |
498 | dra7-evm-lcd-osd101t2587.dtb \ | 501 | dra7-evm-lcd-osd101t2587.dtb \ |
502 | dra7-evm-lcd-osd-late-attach.dtb \ | ||
503 | dra7-evm-fpd-auo-g101evn01.0.dtb \ | ||
504 | dra7-evm-vision.dtb \ | ||
499 | am57xx-beagle-x15.dtb \ | 505 | am57xx-beagle-x15.dtb \ |
500 | am57xx-beagle-x15-revb1.dtb \ | 506 | am57xx-beagle-x15-revb1.dtb \ |
501 | am571x-idk.dtb \ | 507 | am571x-idk.dtb \ |
@@ -510,12 +516,15 @@ dtb-$(CONFIG_SOC_DRA7XX) += \ | |||
510 | dra72-evm-lcd-lg.dtb \ | 516 | dra72-evm-lcd-lg.dtb \ |
511 | dra72-evm-lcd-osd.dtb \ | 517 | dra72-evm-lcd-osd.dtb \ |
512 | dra72-evm-lcd-osd101t2587.dtb \ | 518 | dra72-evm-lcd-osd101t2587.dtb \ |
519 | dra72-evm-fpd-lg.dtb \ | ||
513 | dra72-evm-revc.dtb \ | 520 | dra72-evm-revc.dtb \ |
514 | dra72-evm-revc-lcd-osd101t2045.dtb \ | 521 | dra72-evm-revc-lcd-osd101t2045.dtb \ |
515 | dra72-evm-revc-lcd-osd101t2587.dtb \ | 522 | dra72-evm-revc-lcd-osd101t2587.dtb \ |
523 | dra72-evm-vision.dtb \ | ||
516 | dra71-evm.dtb \ | 524 | dra71-evm.dtb \ |
517 | dra71-evm-lcd-auo-g101evn01.0.dtb \ | 525 | dra71-evm-lcd-auo-g101evn01.0.dtb \ |
518 | dra76-evm.dtb | 526 | dra76-evm.dtb \ |
527 | dra76-evm-fpd-auo-g101evn01.0.dtb | ||
519 | dtb-$(CONFIG_ARCH_ORION5X) += \ | 528 | dtb-$(CONFIG_ARCH_ORION5X) += \ |
520 | orion5x-lacie-d2-network.dtb \ | 529 | orion5x-lacie-d2-network.dtb \ |
521 | orion5x-lacie-ethernet-disk-mini-v2.dtb \ | 530 | orion5x-lacie-ethernet-disk-mini-v2.dtb \ |
diff --git a/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi b/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi index da403a8debd4..f010d6ff4e2d 100644 --- a/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi +++ b/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi | |||
@@ -20,9 +20,8 @@ | |||
20 | rtc1 = &tps659038_rtc; | 20 | rtc1 = &tps659038_rtc; |
21 | rtc2 = &rtc; | 21 | rtc2 = &rtc; |
22 | display0 = &hdmi0; | 22 | display0 = &hdmi0; |
23 | |||
24 | sound0 = &sound0; | 23 | sound0 = &sound0; |
25 | sound1 = &hdmi; | 24 | sound1 = &hdmi0; |
26 | }; | 25 | }; |
27 | 26 | ||
28 | memory { | 27 | memory { |
diff --git a/arch/arm/boot/dts/dra7-evm-common.dtsi b/arch/arm/boot/dts/dra7-evm-common.dtsi index cadf0e6dd430..2bbc04791628 100644 --- a/arch/arm/boot/dts/dra7-evm-common.dtsi +++ b/arch/arm/boot/dts/dra7-evm-common.dtsi | |||
@@ -46,7 +46,7 @@ | |||
46 | 46 | ||
47 | sound0_master: simple-audio-card,cpu { | 47 | sound0_master: simple-audio-card,cpu { |
48 | sound-dai = <&mcasp3>; | 48 | sound-dai = <&mcasp3>; |
49 | system-clock-frequency = <5644800>; | 49 | system-clock-frequency = <11289600>; |
50 | }; | 50 | }; |
51 | 51 | ||
52 | simple-audio-card,codec { | 52 | simple-audio-card,codec { |
@@ -266,9 +266,11 @@ | |||
266 | <&atl_gfclk_mux>, | 266 | <&atl_gfclk_mux>, |
267 | <&dpll_abe_ck>, | 267 | <&dpll_abe_ck>, |
268 | <&dpll_abe_m2x2_ck>, | 268 | <&dpll_abe_m2x2_ck>, |
269 | <&atl_clkin1_ck>, | ||
269 | <&atl_clkin2_ck>; | 270 | <&atl_clkin2_ck>; |
270 | assigned-clock-parents = <&sys_clkin2>, <&dpll_abe_m2_ck>; | 271 | assigned-clock-parents = <&sys_clkin2>, <&dpll_abe_m2_ck>; |
271 | assigned-clock-rates = <0>, <0>, <180633600>, <361267200>, <5644800>; | 272 | assigned-clock-rates = <0>, <0>, <180633600>, <361267200>, |
273 | <11289600>, <11289600>; | ||
272 | 274 | ||
273 | status = "okay"; | 275 | status = "okay"; |
274 | 276 | ||
diff --git a/arch/arm/boot/dts/dra7-evm-fpd-auo-g101evn01.0.dts b/arch/arm/boot/dts/dra7-evm-fpd-auo-g101evn01.0.dts new file mode 100644 index 000000000000..64e79754bb22 --- /dev/null +++ b/arch/arm/boot/dts/dra7-evm-fpd-auo-g101evn01.0.dts | |||
@@ -0,0 +1,37 @@ | |||
1 | #include "dra7-evm.dts" | ||
2 | #include "dra7x-evm-fpd-auo-g101evn01.0.dtsi" | ||
3 | |||
4 | / { | ||
5 | aliases { | ||
6 | display0 = &fpd_disp; | ||
7 | display1 = &hdmi0; | ||
8 | }; | ||
9 | }; | ||
10 | |||
11 | &dss { | ||
12 | ports { | ||
13 | status = "ok"; | ||
14 | }; | ||
15 | }; | ||
16 | |||
17 | &disp_ser { | ||
18 | status = "ok"; | ||
19 | ranges = <0x0 0x2d>; | ||
20 | }; | ||
21 | |||
22 | /* Tie the end points of DSS and FPDLink together */ | ||
23 | |||
24 | &fpd_in { | ||
25 | remote-endpoint = <&dpi_out3>; | ||
26 | }; | ||
27 | |||
28 | &dpi_out3 { | ||
29 | remote-endpoint = <&fpd_in>; | ||
30 | }; | ||
31 | |||
32 | &lcd_fpd { | ||
33 | enable-gpios = <&pcf_gpio_21 0 GPIO_ACTIVE_LOW>; | ||
34 | /* P0, SEL_GPMC_AD_VID_S0 */ | ||
35 | |||
36 | status = "ok"; | ||
37 | }; | ||
diff --git a/arch/arm/boot/dts/dra7-evm-fpd-lg.dts b/arch/arm/boot/dts/dra7-evm-fpd-lg.dts new file mode 100644 index 000000000000..b8df0766ecff --- /dev/null +++ b/arch/arm/boot/dts/dra7-evm-fpd-lg.dts | |||
@@ -0,0 +1,38 @@ | |||
1 | #include "dra7-evm.dts" | ||
2 | #include "dra7x-evm-fpd-lg.dtsi" | ||
3 | |||
4 | / { | ||
5 | aliases { | ||
6 | display0 = &fpd_disp; | ||
7 | display1 = &hdmi0; | ||
8 | }; | ||
9 | }; | ||
10 | |||
11 | &dss { | ||
12 | ports { | ||
13 | status = "ok"; | ||
14 | }; | ||
15 | }; | ||
16 | |||
17 | &disp_ser { | ||
18 | status = "ok"; | ||
19 | ranges = <0x2c 0x2c>, | ||
20 | <0x1c 0x1c>; | ||
21 | }; | ||
22 | |||
23 | /* Tie the end points of DSS and FPDLink together */ | ||
24 | |||
25 | &fpd_in { | ||
26 | remote-endpoint = <&dpi_out3>; | ||
27 | }; | ||
28 | |||
29 | &dpi_out3 { | ||
30 | remote-endpoint = <&fpd_in>; | ||
31 | }; | ||
32 | |||
33 | &lcd_fpd { | ||
34 | enable-gpios = <&pcf_gpio_21 0 GPIO_ACTIVE_LOW>; | ||
35 | /* P0, SEL_GPMC_AD_VID_S0 */ | ||
36 | |||
37 | status = "ok"; | ||
38 | }; | ||
diff --git a/arch/arm/boot/dts/dra7-evm-lcd-lg-late-attach-no-map.dts b/arch/arm/boot/dts/dra7-evm-lcd-lg-late-attach-no-map.dts new file mode 100644 index 000000000000..e15f7bdc0eed --- /dev/null +++ b/arch/arm/boot/dts/dra7-evm-lcd-lg-late-attach-no-map.dts | |||
@@ -0,0 +1,179 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include "dra7-evm-lcd-lg.dts" | ||
10 | |||
11 | /* | ||
12 | * Memory reserved for IOMMU table carveout 0xbfc00000 for length 0x100000 | ||
13 | * Page Table Address for IPU1 0xbfc00000 | ||
14 | * Page Table Address for IPU2 0xbfc08000 | ||
15 | * Page Table Address for DSP1 0xbfc10000 | ||
16 | * Page Table Address for DSP2 0xbfc18000 | ||
17 | */ | ||
18 | |||
19 | &reserved_mem { | ||
20 | latea_pagetbl: late_pgtbl@bfc00000 { | ||
21 | reg = <0x0 0xbfc00000 0x0 0x100000>; | ||
22 | no-map; | ||
23 | status = "okay"; | ||
24 | }; | ||
25 | }; | ||
26 | |||
27 | &ipu2_cma_pool { | ||
28 | /delete-property/ reusable; | ||
29 | no-map; | ||
30 | }; | ||
31 | |||
32 | &ipu2 { | ||
33 | ti,late-attach; | ||
34 | ti,no-idle-on-init; | ||
35 | ti,no-reset-on-init; | ||
36 | }; | ||
37 | |||
38 | &timer3 { | ||
39 | ti,late-attach; | ||
40 | ti,no-idle-on-init; | ||
41 | ti,no-reset-on-init; | ||
42 | }; | ||
43 | |||
44 | &timer4 { | ||
45 | ti,late-attach; | ||
46 | ti,no-idle-on-init; | ||
47 | ti,no-reset-on-init; | ||
48 | }; | ||
49 | |||
50 | &timer9 { | ||
51 | ti,late-attach; | ||
52 | ti,no-idle-on-init; | ||
53 | ti,no-reset-on-init; | ||
54 | }; | ||
55 | |||
56 | &mmu_ipu2{ | ||
57 | ti,late-attach; | ||
58 | ti,late-attach-dma-pool; | ||
59 | ti,no-idle-on-init; | ||
60 | ti,no-reset-on-init; | ||
61 | }; | ||
62 | |||
63 | /* Uncomment below block to enable late attach for IPU1 */ | ||
64 | |||
65 | /* | ||
66 | &ipu1_cma_pool { | ||
67 | /delete-property/ reusable; | ||
68 | no-map; | ||
69 | }; | ||
70 | |||
71 | &ipu1 { | ||
72 | ti,late-attach; | ||
73 | ti,no-idle-on-init; | ||
74 | ti,no-reset-on-init; | ||
75 | }; | ||
76 | |||
77 | &timer11 { | ||
78 | ti,late-attach; | ||
79 | ti,no-idle-on-init; | ||
80 | ti,no-reset-on-init; | ||
81 | }; | ||
82 | |||
83 | &timer7 { | ||
84 | ti,late-attach; | ||
85 | ti,no-idle-on-init; | ||
86 | ti,no-reset-on-init; | ||
87 | }; | ||
88 | |||
89 | &timer8 { | ||
90 | ti,late-attach; | ||
91 | ti,no-idle-on-init; | ||
92 | ti,no-reset-on-init; | ||
93 | }; | ||
94 | |||
95 | &mmu_ipu1{ | ||
96 | ti,late-attach; | ||
97 | ti,late-attach-dma-pool; | ||
98 | ti,no-idle-on-init; | ||
99 | ti,no-reset-on-init; | ||
100 | }; | ||
101 | */ | ||
102 | |||
103 | /* Uncomment below block to enable late attach for DSP1 */ | ||
104 | |||
105 | /* | ||
106 | &dsp1_cma_pool { | ||
107 | /delete-property/ reusable; | ||
108 | no-map; | ||
109 | }; | ||
110 | |||
111 | &dsp1 { | ||
112 | ti,late-attach; | ||
113 | ti,no-idle-on-init; | ||
114 | ti,no-reset-on-init; | ||
115 | }; | ||
116 | |||
117 | &timer5 { | ||
118 | ti,late-attach; | ||
119 | ti,no-idle-on-init; | ||
120 | ti,no-reset-on-init; | ||
121 | }; | ||
122 | |||
123 | &timer10 { | ||
124 | ti,late-attach; | ||
125 | ti,no-idle-on-init; | ||
126 | ti,no-reset-on-init; | ||
127 | }; | ||
128 | |||
129 | &mmu0_dsp1 { | ||
130 | ti,late-attach; | ||
131 | ti,late-attach-dma-pool; | ||
132 | ti,no-idle-on-init; | ||
133 | ti,no-reset-on-init; | ||
134 | }; | ||
135 | |||
136 | &mmu1_dsp1 { | ||
137 | ti,late-attach; | ||
138 | ti,late-attach-dma-pool; | ||
139 | ti,no-idle-on-init; | ||
140 | ti,no-reset-on-init; | ||
141 | }; | ||
142 | */ | ||
143 | |||
144 | /* Uncomment below block to enable late attach for DSP2 */ | ||
145 | |||
146 | /* | ||
147 | |||
148 | &dsp2_cma_pool { | ||
149 | /delete-property/ reusable; | ||
150 | no-map; | ||
151 | }; | ||
152 | |||
153 | &dsp2 { | ||
154 | ti,late-attach; | ||
155 | ti,no-idle-on-init; | ||
156 | ti,no-reset-on-init; | ||
157 | }; | ||
158 | |||
159 | &timer6 { | ||
160 | ti,late-attach; | ||
161 | ti,no-idle-on-init; | ||
162 | ti,no-reset-on-init; | ||
163 | }; | ||
164 | |||
165 | &mmu0_dsp2 { | ||
166 | ti,late-attach; | ||
167 | ti,late-attach-dma-pool; | ||
168 | ti,no-idle-on-init; | ||
169 | ti,no-reset-on-init; | ||
170 | }; | ||
171 | |||
172 | &mmu1_dsp2 { | ||
173 | ti,late-attach; | ||
174 | ti,late-attach-dma-pool; | ||
175 | ti,no-idle-on-init; | ||
176 | ti,no-reset-on-init; | ||
177 | }; | ||
178 | |||
179 | */ | ||
diff --git a/arch/arm/boot/dts/dra7-evm-lcd-lg-late-attach.dts b/arch/arm/boot/dts/dra7-evm-lcd-lg-late-attach.dts new file mode 100644 index 000000000000..939896b6e00b --- /dev/null +++ b/arch/arm/boot/dts/dra7-evm-lcd-lg-late-attach.dts | |||
@@ -0,0 +1,153 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include "dra7-evm-lcd-lg.dts" | ||
10 | |||
11 | /* | ||
12 | * Memory reserved for IOMMU table carveout 0xbfc00000 for length 0x100000 | ||
13 | * Page Table Address for IPU1 0xbfc00000 | ||
14 | * Page Table Address for IPU2 0xbfc08000 | ||
15 | * Page Table Address for DSP1 0xbfc10000 | ||
16 | * Page Table Address for DSP2 0xbfc18000 | ||
17 | */ | ||
18 | |||
19 | &reserved_mem { | ||
20 | latea_pagetbl: late_pgtbl@bfc00000 { | ||
21 | reg = <0x0 0xbfc00000 0x0 0x100000>; | ||
22 | no-map; | ||
23 | status = "okay"; | ||
24 | }; | ||
25 | }; | ||
26 | |||
27 | &ipu2 { | ||
28 | ti,late-attach; | ||
29 | ti,no-idle-on-init; | ||
30 | ti,no-reset-on-init; | ||
31 | }; | ||
32 | |||
33 | &timer3 { | ||
34 | ti,late-attach; | ||
35 | ti,no-idle-on-init; | ||
36 | ti,no-reset-on-init; | ||
37 | }; | ||
38 | |||
39 | &timer4 { | ||
40 | ti,late-attach; | ||
41 | ti,no-idle-on-init; | ||
42 | ti,no-reset-on-init; | ||
43 | }; | ||
44 | |||
45 | &timer9 { | ||
46 | ti,late-attach; | ||
47 | ti,no-idle-on-init; | ||
48 | ti,no-reset-on-init; | ||
49 | }; | ||
50 | |||
51 | &mmu_ipu2{ | ||
52 | ti,late-attach; | ||
53 | ti,no-idle-on-init; | ||
54 | ti,no-reset-on-init; | ||
55 | }; | ||
56 | |||
57 | /* Uncomment below block to enable late attach for IPU1 */ | ||
58 | |||
59 | /* | ||
60 | &ipu1 { | ||
61 | ti,late-attach; | ||
62 | ti,no-idle-on-init; | ||
63 | ti,no-reset-on-init; | ||
64 | }; | ||
65 | |||
66 | &timer11 { | ||
67 | ti,late-attach; | ||
68 | ti,no-idle-on-init; | ||
69 | ti,no-reset-on-init; | ||
70 | }; | ||
71 | |||
72 | &timer7 { | ||
73 | ti,late-attach; | ||
74 | ti,no-idle-on-init; | ||
75 | ti,no-reset-on-init; | ||
76 | }; | ||
77 | |||
78 | &timer8 { | ||
79 | ti,late-attach; | ||
80 | ti,no-idle-on-init; | ||
81 | ti,no-reset-on-init; | ||
82 | }; | ||
83 | |||
84 | &mmu_ipu1{ | ||
85 | ti,late-attach; | ||
86 | ti,no-idle-on-init; | ||
87 | ti,no-reset-on-init; | ||
88 | }; | ||
89 | */ | ||
90 | |||
91 | /* Uncomment below block to enable late attach for DSP1 */ | ||
92 | |||
93 | /* | ||
94 | &dsp1 { | ||
95 | ti,late-attach; | ||
96 | ti,no-idle-on-init; | ||
97 | ti,no-reset-on-init; | ||
98 | }; | ||
99 | |||
100 | &timer5 { | ||
101 | ti,late-attach; | ||
102 | ti,no-idle-on-init; | ||
103 | ti,no-reset-on-init; | ||
104 | }; | ||
105 | |||
106 | &timer10 { | ||
107 | ti,late-attach; | ||
108 | ti,no-idle-on-init; | ||
109 | ti,no-reset-on-init; | ||
110 | }; | ||
111 | |||
112 | &mmu0_dsp1 { | ||
113 | ti,late-attach; | ||
114 | ti,no-idle-on-init; | ||
115 | ti,no-reset-on-init; | ||
116 | }; | ||
117 | |||
118 | &mmu1_dsp1 { | ||
119 | ti,late-attach; | ||
120 | ti,no-idle-on-init; | ||
121 | ti,no-reset-on-init; | ||
122 | }; | ||
123 | */ | ||
124 | |||
125 | /* Uncomment below block to enable late attach for DSP2 */ | ||
126 | |||
127 | /* | ||
128 | |||
129 | &dsp2 { | ||
130 | ti,late-attach; | ||
131 | ti,no-idle-on-init; | ||
132 | ti,no-reset-on-init; | ||
133 | }; | ||
134 | |||
135 | &timer6 { | ||
136 | ti,late-attach; | ||
137 | ti,no-idle-on-init; | ||
138 | ti,no-reset-on-init; | ||
139 | }; | ||
140 | |||
141 | &mmu0_dsp2 { | ||
142 | ti,late-attach; | ||
143 | ti,no-idle-on-init; | ||
144 | ti,no-reset-on-init; | ||
145 | }; | ||
146 | |||
147 | &mmu1_dsp2 { | ||
148 | ti,late-attach; | ||
149 | ti,no-idle-on-init; | ||
150 | ti,no-reset-on-init; | ||
151 | }; | ||
152 | |||
153 | */ | ||
diff --git a/arch/arm/boot/dts/dra7-evm-lcd-lg.dts b/arch/arm/boot/dts/dra7-evm-lcd-lg.dts index d2653938d051..2b09d3a8839f 100644 --- a/arch/arm/boot/dts/dra7-evm-lcd-lg.dts +++ b/arch/arm/boot/dts/dra7-evm-lcd-lg.dts | |||
@@ -8,3 +8,17 @@ | |||
8 | 8 | ||
9 | #include "dra7-evm.dts" | 9 | #include "dra7-evm.dts" |
10 | #include "dra7x-evm-lcd-lg.dtsi" | 10 | #include "dra7x-evm-lcd-lg.dtsi" |
11 | |||
12 | &ldc3001 { | ||
13 | interrupt-parent = <&gpio1>; | ||
14 | interrupts = <2 IRQ_TYPE_LEVEL_HIGH>; | ||
15 | }; | ||
16 | |||
17 | |||
18 | /* Uncomment the below lines to enable the FPDLink display */ | ||
19 | |||
20 | /* | ||
21 | &lcd_fpd { | ||
22 | status = "okay"; | ||
23 | }; | ||
24 | */ | ||
diff --git a/arch/arm/boot/dts/dra7-evm-lcd-osd-late-attach.dts b/arch/arm/boot/dts/dra7-evm-lcd-osd-late-attach.dts new file mode 100644 index 000000000000..5416d2645517 --- /dev/null +++ b/arch/arm/boot/dts/dra7-evm-lcd-osd-late-attach.dts | |||
@@ -0,0 +1,152 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include "dra7-evm-lcd-osd.dts" | ||
10 | |||
11 | /* | ||
12 | * Memory reserved for IOMMU table carveout 0xbfc00000 for length 0x100000 | ||
13 | * Page Table Address for IPU1 0xbfc00000 | ||
14 | * Page Table Address for IPU2 0xbfc08000 | ||
15 | * Page Table Address for DSP1 0xbfc10000 | ||
16 | * Page Table Address for DSP2 0xbfc18000 | ||
17 | */ | ||
18 | |||
19 | &reserved_mem { | ||
20 | latea_pagetbl: late_pgtbl@bfc00000 { | ||
21 | reg = <0x0 0xbfc00000 0x0 0x100000>; | ||
22 | no-map; | ||
23 | status = "okay"; | ||
24 | }; | ||
25 | }; | ||
26 | |||
27 | &ipu2 { | ||
28 | ti,late-attach; | ||
29 | ti,no-idle-on-init; | ||
30 | ti,no-reset-on-init; | ||
31 | }; | ||
32 | |||
33 | &timer3 { | ||
34 | ti,late-attach; | ||
35 | ti,no-idle-on-init; | ||
36 | ti,no-reset-on-init; | ||
37 | }; | ||
38 | |||
39 | &timer4 { | ||
40 | ti,late-attach; | ||
41 | ti,no-idle-on-init; | ||
42 | ti,no-reset-on-init; | ||
43 | }; | ||
44 | |||
45 | &timer9 { | ||
46 | ti,late-attach; | ||
47 | ti,no-idle-on-init; | ||
48 | ti,no-reset-on-init; | ||
49 | }; | ||
50 | |||
51 | &mmu_ipu2{ | ||
52 | ti,late-attach; | ||
53 | ti,no-idle-on-init; | ||
54 | ti,no-reset-on-init; | ||
55 | }; | ||
56 | |||
57 | /*Uncomment below block to enable late attach for IPU1*/ | ||
58 | |||
59 | /* | ||
60 | &ipu1 { | ||
61 | ti,late-attach; | ||
62 | ti,no-idle-on-init; | ||
63 | ti,no-reset-on-init; | ||
64 | }; | ||
65 | |||
66 | &timer11 { | ||
67 | ti,late-attach; | ||
68 | ti,no-idle-on-init; | ||
69 | ti,no-reset-on-init; | ||
70 | }; | ||
71 | |||
72 | &timer7 { | ||
73 | ti,late-attach; | ||
74 | ti,no-idle-on-init; | ||
75 | ti,no-reset-on-init; | ||
76 | }; | ||
77 | |||
78 | &timer8 { | ||
79 | ti,late-attach; | ||
80 | ti,no-idle-on-init; | ||
81 | ti,no-reset-on-init; | ||
82 | }; | ||
83 | |||
84 | &mmu_ipu1{ | ||
85 | ti,late-attach; | ||
86 | ti,no-idle-on-init; | ||
87 | ti,no-reset-on-init; | ||
88 | }; | ||
89 | */ | ||
90 | |||
91 | /*Uncomment below block to enable late attach for DSP1*/ | ||
92 | |||
93 | /* | ||
94 | &dsp1 { | ||
95 | ti,late-attach; | ||
96 | ti,no-idle-on-init; | ||
97 | ti,no-reset-on-init; | ||
98 | }; | ||
99 | |||
100 | &timer5 { | ||
101 | ti,late-attach; | ||
102 | ti,no-idle-on-init; | ||
103 | ti,no-reset-on-init; | ||
104 | }; | ||
105 | |||
106 | &timer10 { | ||
107 | ti,late-attach; | ||
108 | ti,no-idle-on-init; | ||
109 | ti,no-reset-on-init; | ||
110 | }; | ||
111 | |||
112 | &mmu0_dsp1 { | ||
113 | ti,late-attach; | ||
114 | ti,no-idle-on-init; | ||
115 | ti,no-reset-on-init; | ||
116 | }; | ||
117 | |||
118 | &mmu1_dsp1 { | ||
119 | ti,late-attach; | ||
120 | ti,no-idle-on-init; | ||
121 | ti,no-reset-on-init; | ||
122 | }; | ||
123 | */ | ||
124 | |||
125 | /*Uncomment below block to enable late attach for DSP2*/ | ||
126 | |||
127 | /* | ||
128 | &dsp2 { | ||
129 | ti,late-attach; | ||
130 | ti,no-idle-on-init; | ||
131 | ti,no-reset-on-init; | ||
132 | }; | ||
133 | |||
134 | &timer6 { | ||
135 | ti,late-attach; | ||
136 | ti,no-idle-on-init; | ||
137 | ti,no-reset-on-init; | ||
138 | }; | ||
139 | |||
140 | &mmu0_dsp2 { | ||
141 | ti,late-attach; | ||
142 | ti,no-idle-on-init; | ||
143 | ti,no-reset-on-init; | ||
144 | }; | ||
145 | |||
146 | &mmu1_dsp2 { | ||
147 | ti,late-attach; | ||
148 | ti,no-idle-on-init; | ||
149 | ti,no-reset-on-init; | ||
150 | }; | ||
151 | */ | ||
152 | |||
diff --git a/arch/arm/boot/dts/dra7-evm-vision.dts b/arch/arm/boot/dts/dra7-evm-vision.dts new file mode 100644 index 000000000000..5c00f3b76655 --- /dev/null +++ b/arch/arm/boot/dts/dra7-evm-vision.dts | |||
@@ -0,0 +1,130 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include "dra7-evm.dts" | ||
10 | |||
11 | i2cexp: &i2c2 { | ||
12 | }; | ||
13 | |||
14 | #include "dra7xx-vision.dtsi" | ||
15 | |||
16 | /* | ||
17 | * Following is the mapping of the cameras and video ports: | ||
18 | * | ||
19 | * +--------+---------+---------+---------+---------+ | ||
20 | * | LVDS | DES I2C | Remote | SER I2C | CAM I2C | | ||
21 | * | Camera | Addr | I2C bus | Alias | Alias | | ||
22 | * +--------+---------+---------+---------+---------+ | ||
23 | * | cam1 | 0x60 | 11 | 0x74 | 0x38 | | ||
24 | * | cam2 | 0x64 | 12 | 0x75 | 0x39 | | ||
25 | * | cam3 | 0x68 | 13 | 0x76 | 0x3A | | ||
26 | * | cam4 | 0x6C | 14 | 0x77 | 0x3B | | ||
27 | * | cam5 | 0x69 | 15 | 0x78 | 0x3C | | ||
28 | * | cam6 | 0x61 | 16 | 0x79 | 0x3D | | ||
29 | * +--------+---------+---------+---------+---------+ | ||
30 | * | ||
31 | * For easier access, all the remote devices can be accessed using the | ||
32 | * remote bus as well as the local bus. e.g. remote Serializer can be | ||
33 | * accessed as 11-0058 as well as 1-0074 | ||
34 | */ | ||
35 | &vip1 { | ||
36 | status = "okay"; | ||
37 | }; | ||
38 | |||
39 | &vip2 { | ||
40 | status = "okay"; | ||
41 | }; | ||
42 | |||
43 | &vip3 { | ||
44 | status = "okay"; | ||
45 | }; | ||
46 | |||
47 | &ovcam_fc { | ||
48 | /* Select between onboard OV10633 camera and daughter card vin | ||
49 | * Also enable power for the OVcamera externally | ||
50 | */ | ||
51 | mux-gpios = | ||
52 | <&pcf_hdmi 3 GPIO_ACTIVE_HIGH>, /* CAM_FPD_MUX_S0 */ | ||
53 | <&gpio6 17 GPIO_ACTIVE_HIGH>; /* OV_PWDN */ | ||
54 | }; | ||
55 | |||
56 | &ovcam1 { | ||
57 | /* Select between onboard OV10633 camera and daughter card vin */ | ||
58 | mux-gpios = | ||
59 | <&pcf_hdmi 3 GPIO_ACTIVE_HIGH>; /* CAM_FPD_MUX_S0 */ | ||
60 | }; | ||
61 | |||
62 | &ovcam2 { | ||
63 | /* Select between vin2a and ethernet slave0 */ | ||
64 | mux-gpios = | ||
65 | <&pcf_hdmi 2 GPIO_ACTIVE_LOW>; /* VIN2_S0 */ | ||
66 | }; | ||
67 | |||
68 | &ovcam3 { | ||
69 | /* No board muxes */ | ||
70 | }; | ||
71 | |||
72 | &ovcam4 { | ||
73 | /* No board muxes */ | ||
74 | }; | ||
75 | |||
76 | &ovcam5 { | ||
77 | /* No board muxes */ | ||
78 | }; | ||
79 | |||
80 | /* Main board hogs this GPIO, it should be set by the camera driver */ | ||
81 | /delete-node/ &vin6_brdmux; | ||
82 | |||
83 | &ovcam6 { | ||
84 | mux-gpios = | ||
85 | <&pcf_hdmi 1 GPIO_ACTIVE_HIGH>; /* VIN6_SEL_S0 */ | ||
86 | }; | ||
87 | |||
88 | &vin1a { | ||
89 | status = "okay"; | ||
90 | endpoint@cam1 { | ||
91 | slave-mode; | ||
92 | remote-endpoint = <&cam1>; | ||
93 | }; | ||
94 | endpoint@ovcam { | ||
95 | slave-mode; | ||
96 | remote-endpoint = <&ovcam>; | ||
97 | }; | ||
98 | }; | ||
99 | |||
100 | &vin2a { | ||
101 | status = "okay"; | ||
102 | endpoint@0 { | ||
103 | slave-mode; | ||
104 | remote-endpoint = <&cam2>; | ||
105 | }; | ||
106 | }; | ||
107 | |||
108 | &vin3a { | ||
109 | status = "okay"; | ||
110 | endpoint@0 { | ||
111 | slave-mode; | ||
112 | remote-endpoint = <&cam3>; | ||
113 | }; | ||
114 | }; | ||
115 | |||
116 | &vin5a { | ||
117 | status = "okay"; | ||
118 | endpoint@0 { | ||
119 | slave-mode; | ||
120 | remote-endpoint = <&cam4>; | ||
121 | }; | ||
122 | }; | ||
123 | |||
124 | &vin6a { | ||
125 | status = "okay"; | ||
126 | endpoint@0 { | ||
127 | slave-mode; | ||
128 | remote-endpoint = <&cam6>; | ||
129 | }; | ||
130 | }; | ||
diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts index e8ddc3b9d047..aee34b6d45c1 100644 --- a/arch/arm/boot/dts/dra7-evm.dts +++ b/arch/arm/boot/dts/dra7-evm.dts | |||
@@ -19,7 +19,7 @@ | |||
19 | reg = <0x0 0x80000000 0x0 0x60000000>; /* 1536 MB */ | 19 | reg = <0x0 0x80000000 0x0 0x60000000>; /* 1536 MB */ |
20 | }; | 20 | }; |
21 | 21 | ||
22 | reserved-memory { | 22 | reserved_mem: reserved-memory { |
23 | #address-cells = <2>; | 23 | #address-cells = <2>; |
24 | #size-cells = <2>; | 24 | #size-cells = <2>; |
25 | ranges; | 25 | ranges; |
@@ -53,6 +53,10 @@ | |||
53 | }; | 53 | }; |
54 | }; | 54 | }; |
55 | 55 | ||
56 | aliases { | ||
57 | i2c7 = &disp_ser; | ||
58 | }; | ||
59 | |||
56 | evm_1v8_sw: fixedregulator-evm_1v8 { | 60 | evm_1v8_sw: fixedregulator-evm_1v8 { |
57 | compatible = "regulator-fixed"; | 61 | compatible = "regulator-fixed"; |
58 | regulator-name = "evm_1v8"; | 62 | regulator-name = "evm_1v8"; |
@@ -806,7 +810,7 @@ | |||
806 | }; | 810 | }; |
807 | }; | 811 | }; |
808 | 812 | ||
809 | &i2c2 { | 813 | i2c_p3_exp: &i2c2 { |
810 | status = "okay"; | 814 | status = "okay"; |
811 | clock-frequency = <400000>; | 815 | clock-frequency = <400000>; |
812 | 816 | ||
@@ -815,7 +819,7 @@ | |||
815 | reg = <0x26>; | 819 | reg = <0x26>; |
816 | gpio-controller; | 820 | gpio-controller; |
817 | #gpio-cells = <2>; | 821 | #gpio-cells = <2>; |
818 | p1 { | 822 | vin6_brdmux: p1 { |
819 | /* vin6_sel_s0: high: VIN6, low: audio */ | 823 | /* vin6_sel_s0: high: VIN6, low: audio */ |
820 | gpio-hog; | 824 | gpio-hog; |
821 | gpios = <1 GPIO_ACTIVE_HIGH>; | 825 | gpios = <1 GPIO_ACTIVE_HIGH>; |
@@ -838,6 +842,15 @@ | |||
838 | }; | 842 | }; |
839 | }; | 843 | }; |
840 | }; | 844 | }; |
845 | |||
846 | disp_ser: serializer@1b { | ||
847 | compatible = "ti,ds90uh925q"; | ||
848 | reg = <0x1b>; | ||
849 | |||
850 | #address-cells = <1>; | ||
851 | #size-cells = <0>; | ||
852 | status = "disabled"; | ||
853 | }; | ||
841 | }; | 854 | }; |
842 | 855 | ||
843 | &mmc1 { | 856 | &mmc1 { |
@@ -1046,9 +1059,23 @@ | |||
1046 | }; | 1059 | }; |
1047 | 1060 | ||
1048 | &dss { | 1061 | &dss { |
1049 | status = "ok"; | 1062 | status = "okay"; |
1050 | 1063 | ||
1051 | vdda_video-supply = <&ldoln_reg>; | 1064 | vdda_video-supply = <&ldoln_reg>; |
1065 | |||
1066 | ports { | ||
1067 | #address-cells = <1>; | ||
1068 | #size-cells = <0>; | ||
1069 | status = "disabled"; | ||
1070 | |||
1071 | port@lcd3 { | ||
1072 | reg = <2>; | ||
1073 | |||
1074 | dpi_out3: endpoint { | ||
1075 | data-lines = <24>; | ||
1076 | }; | ||
1077 | }; | ||
1078 | }; | ||
1052 | }; | 1079 | }; |
1053 | 1080 | ||
1054 | &hdmi { | 1081 | &hdmi { |
@@ -1060,7 +1087,7 @@ | |||
1060 | status = "okay"; | 1087 | status = "okay"; |
1061 | }; | 1088 | }; |
1062 | 1089 | ||
1063 | &vin1a { | 1090 | video_in: &vin1a { |
1064 | status = "okay"; | 1091 | status = "okay"; |
1065 | endpoint@0 { | 1092 | endpoint@0 { |
1066 | slave-mode; | 1093 | slave-mode; |
@@ -1072,3 +1099,8 @@ | |||
1072 | status = "okay"; | 1099 | status = "okay"; |
1073 | }; | 1100 | }; |
1074 | 1101 | ||
1102 | #include "dra7xx-jamr3.dtsi" | ||
1103 | &tvp_5158{ | ||
1104 | mux-gpios = <&pcf_hdmi 3 GPIO_ACTIVE_HIGH>, /*CAM_FPD_MUX_S0*/ | ||
1105 | <&pcf_jamr3_21 8 GPIO_ACTIVE_LOW>; /*SEL_TVP_FPD*/ | ||
1106 | }; | ||
diff --git a/arch/arm/boot/dts/dra71-evm.dts b/arch/arm/boot/dts/dra71-evm.dts index 42ca589606a9..1a6cb83fddb8 100644 --- a/arch/arm/boot/dts/dra71-evm.dts +++ b/arch/arm/boot/dts/dra71-evm.dts | |||
@@ -18,7 +18,7 @@ | |||
18 | reg = <0x0 0x80000000 0x0 0x80000000>; /* 2GB */ | 18 | reg = <0x0 0x80000000 0x0 0x80000000>; /* 2GB */ |
19 | }; | 19 | }; |
20 | 20 | ||
21 | reserved-memory { | 21 | reserved_mem: reserved-memory { |
22 | #address-cells = <2>; | 22 | #address-cells = <2>; |
23 | #size-cells = <2>; | 23 | #size-cells = <2>; |
24 | ranges; | 24 | ranges; |
@@ -376,7 +376,12 @@ | |||
376 | }; | 376 | }; |
377 | }; | 377 | }; |
378 | 378 | ||
379 | &i2c5 { | 379 | &i2c3 { |
380 | status = "okay"; | ||
381 | clock-frequency = <400000>; | ||
382 | }; | ||
383 | |||
384 | i2c_p3_exp: &i2c5 { | ||
380 | status = "okay"; | 385 | status = "okay"; |
381 | clock-frequency = <400000>; | 386 | clock-frequency = <400000>; |
382 | 387 | ||
@@ -430,7 +435,7 @@ | |||
430 | status = "okay"; | 435 | status = "okay"; |
431 | }; | 436 | }; |
432 | 437 | ||
433 | &vin2a { | 438 | video_in: &vin2a { |
434 | status = "okay"; | 439 | status = "okay"; |
435 | endpoint@0 { | 440 | endpoint@0 { |
436 | slave-mode; | 441 | slave-mode; |
@@ -584,3 +589,10 @@ | |||
584 | status = "okay"; | 589 | status = "okay"; |
585 | memory-region = <&dsp1_cma_pool>; | 590 | memory-region = <&dsp1_cma_pool>; |
586 | }; | 591 | }; |
592 | |||
593 | #include "dra7xx-jamr3.dtsi" | ||
594 | &tvp_5158{ | ||
595 | mux-gpios = <&pcf_hdmi 2 GPIO_ACTIVE_LOW>, /*VIN2_S0*/ | ||
596 | <&pcf_jamr3_21 8 GPIO_ACTIVE_LOW>, /*SEL_TVP_FPD*/ | ||
597 | <&pcf_hdmi 6 GPIO_ACTIVE_HIGH>; /*VIN2_S2*/ | ||
598 | }; | ||
diff --git a/arch/arm/boot/dts/dra72-evm-common.dtsi b/arch/arm/boot/dts/dra72-evm-common.dtsi index f914e6ac0256..1896ef30f673 100644 --- a/arch/arm/boot/dts/dra72-evm-common.dtsi +++ b/arch/arm/boot/dts/dra72-evm-common.dtsi | |||
@@ -16,9 +16,9 @@ | |||
16 | 16 | ||
17 | aliases { | 17 | aliases { |
18 | display0 = &hdmi0; | 18 | display0 = &hdmi0; |
19 | 19 | sound0 = &snd0; | |
20 | sound0 = &sound0; | ||
21 | sound1 = &hdmi; | 20 | sound1 = &hdmi; |
21 | i2c7 = &disp_ser; | ||
22 | }; | 22 | }; |
23 | 23 | ||
24 | evm_12v0: fixedregulator-evm12v0 { | 24 | evm_12v0: fixedregulator-evm12v0 { |
@@ -137,7 +137,7 @@ | |||
137 | }; | 137 | }; |
138 | }; | 138 | }; |
139 | 139 | ||
140 | sound0: sound@0 { | 140 | snd0: sound@0 { |
141 | compatible = "simple-audio-card"; | 141 | compatible = "simple-audio-card"; |
142 | simple-audio-card,name = "DRA7xx-EVM"; | 142 | simple-audio-card,name = "DRA7xx-EVM"; |
143 | simple-audio-card,widgets = | 143 | simple-audio-card,widgets = |
@@ -162,7 +162,7 @@ | |||
162 | 162 | ||
163 | sound0_master: simple-audio-card,cpu { | 163 | sound0_master: simple-audio-card,cpu { |
164 | sound-dai = <&mcasp3>; | 164 | sound-dai = <&mcasp3>; |
165 | system-clock-frequency = <5644800>; | 165 | system-clock-frequency = <11289600>; |
166 | }; | 166 | }; |
167 | 167 | ||
168 | simple-audio-card,codec { | 168 | simple-audio-card,codec { |
@@ -282,7 +282,7 @@ | |||
282 | }; | 282 | }; |
283 | }; | 283 | }; |
284 | 284 | ||
285 | &i2c5 { | 285 | i2c_p3_exp: &i2c5 { |
286 | status = "okay"; | 286 | status = "okay"; |
287 | clock-frequency = <400000>; | 287 | clock-frequency = <400000>; |
288 | 288 | ||
@@ -582,8 +582,34 @@ | |||
582 | }; | 582 | }; |
583 | }; | 583 | }; |
584 | 584 | ||
585 | &i2c5 { | ||
586 | disp_ser: serializer@1b { | ||
587 | compatible = "ti,ds90uh925q"; | ||
588 | reg = <0x1b>; | ||
589 | status = "disabled"; | ||
590 | |||
591 | #address-cells = <1>; | ||
592 | #size-cells = <0>; | ||
593 | }; | ||
594 | }; | ||
595 | |||
596 | |||
585 | &dss { | 597 | &dss { |
586 | status = "ok"; | 598 | status = "ok"; |
599 | vdda_video-supply = <&ldo5_reg>; | ||
600 | ports { | ||
601 | #address-cells = <1>; | ||
602 | #size-cells = <0>; | ||
603 | status = "disabled"; | ||
604 | |||
605 | port@lcd3 { | ||
606 | reg = <2>; | ||
607 | |||
608 | dpi_out3: endpoint { | ||
609 | data-lines = <24>; | ||
610 | }; | ||
611 | }; | ||
612 | }; | ||
587 | }; | 613 | }; |
588 | 614 | ||
589 | &bb2d { | 615 | &bb2d { |
@@ -628,9 +654,11 @@ | |||
628 | <&atl_gfclk_mux>, | 654 | <&atl_gfclk_mux>, |
629 | <&dpll_abe_ck>, | 655 | <&dpll_abe_ck>, |
630 | <&dpll_abe_m2x2_ck>, | 656 | <&dpll_abe_m2x2_ck>, |
657 | <&atl_clkin1_ck>, | ||
631 | <&atl_clkin2_ck>; | 658 | <&atl_clkin2_ck>; |
632 | assigned-clock-parents = <&sys_clkin2>, <&dpll_abe_m2_ck>; | 659 | assigned-clock-parents = <&sys_clkin2>, <&dpll_abe_m2_ck>; |
633 | assigned-clock-rates = <0>, <0>, <180633600>, <361267200>, <5644800>; | 660 | assigned-clock-rates = <0>, <0>, <180633600>, <361267200>, |
661 | <11289600>, <11289600>; | ||
634 | 662 | ||
635 | status = "okay"; | 663 | status = "okay"; |
636 | 664 | ||
diff --git a/arch/arm/boot/dts/dra72-evm-fpd-lg.dts b/arch/arm/boot/dts/dra72-evm-fpd-lg.dts new file mode 100644 index 000000000000..9ed0f66fdb76 --- /dev/null +++ b/arch/arm/boot/dts/dra72-evm-fpd-lg.dts | |||
@@ -0,0 +1,39 @@ | |||
1 | #include "dra72-evm.dts" | ||
2 | #include "dra7x-evm-fpd-lg.dtsi" | ||
3 | |||
4 | /* Set display aliases for use by Android */ | ||
5 | / { | ||
6 | aliases { | ||
7 | display0 = &fpd_disp; | ||
8 | display1 = &hdmi0; | ||
9 | }; | ||
10 | }; | ||
11 | |||
12 | &dss { | ||
13 | ports { | ||
14 | status = "ok"; | ||
15 | }; | ||
16 | }; | ||
17 | |||
18 | &disp_ser { | ||
19 | status = "ok"; | ||
20 | ranges = <0x2c 0x2c>, | ||
21 | <0x1c 0x1c>; | ||
22 | }; | ||
23 | |||
24 | /* Tie the end points of DSS and FPDLink together */ | ||
25 | |||
26 | &fpd_in { | ||
27 | remote-endpoint = <&dpi_out3>; | ||
28 | }; | ||
29 | |||
30 | &dpi_out3 { | ||
31 | remote-endpoint = <&fpd_in>; | ||
32 | }; | ||
33 | |||
34 | &lcd_fpd { | ||
35 | enable-gpios = <&pcf_gpio_21 0 GPIO_ACTIVE_LOW>; | ||
36 | /* P0, SEL_GPMC_AD_VID_S0 */ | ||
37 | |||
38 | status = "ok"; | ||
39 | }; | ||
diff --git a/arch/arm/boot/dts/dra72-evm-revc.dts b/arch/arm/boot/dts/dra72-evm-revc.dts index 5ef7389e979e..517d85f7c294 100644 --- a/arch/arm/boot/dts/dra72-evm-revc.dts +++ b/arch/arm/boot/dts/dra72-evm-revc.dts | |||
@@ -16,7 +16,7 @@ | |||
16 | reg = <0x0 0x80000000 0x0 0x80000000>; /* 2GB */ | 16 | reg = <0x0 0x80000000 0x0 0x80000000>; /* 2GB */ |
17 | }; | 17 | }; |
18 | 18 | ||
19 | reserved-memory { | 19 | reserved_mem: reserved-memory { |
20 | #address-cells = <2>; | 20 | #address-cells = <2>; |
21 | #size-cells = <2>; | 21 | #size-cells = <2>; |
22 | ranges; | 22 | ranges; |
@@ -366,3 +366,18 @@ | |||
366 | status = "okay"; | 366 | status = "okay"; |
367 | memory-region = <&dsp1_cma_pool>; | 367 | memory-region = <&dsp1_cma_pool>; |
368 | }; | 368 | }; |
369 | |||
370 | video_in: &vin2a { | ||
371 | status = "okay"; | ||
372 | endpoint@0 { | ||
373 | slave-mode; | ||
374 | remote-endpoint = <&onboardLI>; | ||
375 | }; | ||
376 | }; | ||
377 | |||
378 | #include "dra7xx-jamr3.dtsi" | ||
379 | &tvp_5158{ | ||
380 | mux-gpios = <&pcf_hdmi 2 GPIO_ACTIVE_LOW>, /*VIN2_S0*/ | ||
381 | <&pcf_jamr3_21 8 GPIO_ACTIVE_LOW>, /*SEL_TVP_FPD*/ | ||
382 | <&pcf_hdmi 6 GPIO_ACTIVE_HIGH>; /*VIN2_S2*/ | ||
383 | }; | ||
diff --git a/arch/arm/boot/dts/dra72-evm-vision.dts b/arch/arm/boot/dts/dra72-evm-vision.dts new file mode 100644 index 000000000000..b59d44f20772 --- /dev/null +++ b/arch/arm/boot/dts/dra72-evm-vision.dts | |||
@@ -0,0 +1,139 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include "dra72-evm-revc.dts" | ||
10 | |||
11 | i2cexp: &i2c5 { | ||
12 | }; | ||
13 | |||
14 | #include "dra7xx-vision.dtsi" | ||
15 | |||
16 | /* | ||
17 | * Following is the mapping of the cameras and video ports: | ||
18 | * This is for the RevC onwards of DRA72 EVMs | ||
19 | * | ||
20 | * +-------+--------+---------+---------+---------+---------+ | ||
21 | * | Video | LVDS | DES I2C | Remote | SER I2C | CAM I2C | | ||
22 | * | Port | Camera | Addr | I2C bus | Alias | Alias | | ||
23 | * +-------+--------+---------+---------+---------+---------+ | ||
24 | * | vin1a | cam2 | 0x64 | 12 | 0x75 | 0x39 | | ||
25 | * | vin1b | cam5 | 0x69 | 15 | 0x78 | 0x3C | | ||
26 | * | vin2a | cam1 | 0x60 | 11 | 0x74 | 0x38 | | ||
27 | * | vin2b | cam4 | 0x6C | 14 | 0x77 | 0x3B | | ||
28 | * +-------+--------+---------+---------+---------+---------+ | ||
29 | * | ||
30 | * For easier access, all the remote devices can be accessed using the | ||
31 | * remote bus as well as the local bus. e.g. remote Serializer can be | ||
32 | * accessed as 11-0058 as well as 4-0074 | ||
33 | */ | ||
34 | |||
35 | &dra72_vip_mux { | ||
36 | |||
37 | pinctrl-names = "default"; | ||
38 | pinctrl-0 = <&vip_mux>; | ||
39 | |||
40 | /* Following is the mapping of interfaces | ||
41 | * vin1A <= vin3A (remapped) | ||
42 | * vin1B <= vin4B (remapped, only available option) | ||
43 | * vin2A <= vin2A (default) | ||
44 | * vin2B <= vin2B (default) | ||
45 | */ | ||
46 | vip_mux: pinmux_vin5a_pins { | ||
47 | pinctrl-single,pins = < | ||
48 | 0x0 (VIP_VIN3A | VIP_VIN4B | VIP_VIN2A | VIP_VIN2B) | ||
49 | >; | ||
50 | }; | ||
51 | }; | ||
52 | |||
53 | &vip1 { | ||
54 | status = "okay"; | ||
55 | }; | ||
56 | |||
57 | &ovcam_fc { | ||
58 | /* Select between onboard OV10633 camera and daughter card vin | ||
59 | * Also enable power for the OVcamera externally | ||
60 | */ | ||
61 | mux-gpios = | ||
62 | <&pcf_hdmi 2 GPIO_ACTIVE_LOW>, /* VIN2_S0 */ | ||
63 | <&pcf_hdmi 6 GPIO_ACTIVE_HIGH>, /* VIN2_S2 */ | ||
64 | <&gpio6 17 GPIO_ACTIVE_HIGH>; /* OV_PWDN */ | ||
65 | }; | ||
66 | |||
67 | &ovcam1 { | ||
68 | /* Select between OV10633 camera, ethernet and external vin2a */ | ||
69 | mux-gpios = | ||
70 | <&pcf_hdmi 2 GPIO_ACTIVE_LOW>, /* VIN2_S0 */ | ||
71 | <&pcf_hdmi 6 GPIO_ACTIVE_HIGH>; /* VIN2_S2 */ | ||
72 | }; | ||
73 | |||
74 | &ovcam2 { | ||
75 | /* Select between GPMC, VOUT3 (FPDlink disp) and external vin1a */ | ||
76 | mux-gpios = | ||
77 | <&pcf_gpio_21 0 GPIO_ACTIVE_HIGH>, /* SEL_GPMC_AD_VID_S0 */ | ||
78 | <&pcf_gpio_21 7 GPIO_ACTIVE_LOW>; /* SEL_GPMC_AD_VID_S2 */ | ||
79 | }; | ||
80 | |||
81 | &ovcam3 { | ||
82 | status = "disabled"; | ||
83 | }; | ||
84 | |||
85 | &ovcam4 { | ||
86 | /* Select */ | ||
87 | mux-gpios = | ||
88 | <&pcf_hdmi 11 GPIO_ACTIVE_LOW>; /* MMC3_SEL */ | ||
89 | }; | ||
90 | |||
91 | &ovcam5 { | ||
92 | /* No board muxes */ | ||
93 | }; | ||
94 | |||
95 | &ovcam6 { | ||
96 | status = "disabled"; | ||
97 | }; | ||
98 | |||
99 | &pcf_gpio_21 { | ||
100 | cpsw_sel_s0 { | ||
101 | status = "disabled"; | ||
102 | }; | ||
103 | }; | ||
104 | |||
105 | &vin1a { | ||
106 | status = "okay"; | ||
107 | endpoint@0 { | ||
108 | slave-mode; | ||
109 | remote-endpoint = <&cam2>; | ||
110 | }; | ||
111 | }; | ||
112 | |||
113 | &vin1b { | ||
114 | status = "okay"; | ||
115 | endpoint@0 { | ||
116 | slave-mode; | ||
117 | remote-endpoint = <&cam5>; | ||
118 | }; | ||
119 | }; | ||
120 | |||
121 | &vin2a { | ||
122 | status = "okay"; | ||
123 | endpoint@0 { | ||
124 | slave-mode; | ||
125 | remote-endpoint = <&cam1>; | ||
126 | }; | ||
127 | endpoint@1 { | ||
128 | slave-mode; | ||
129 | remote-endpoint = <&ovcam>; | ||
130 | }; | ||
131 | }; | ||
132 | |||
133 | &vin2b { | ||
134 | status = "okay"; | ||
135 | endpoint@0 { | ||
136 | slave-mode; | ||
137 | remote-endpoint = <&cam4>; | ||
138 | }; | ||
139 | }; | ||
diff --git a/arch/arm/boot/dts/dra72-evm.dts b/arch/arm/boot/dts/dra72-evm.dts index c2a4bc1ad423..cc108d2f9b09 100644 --- a/arch/arm/boot/dts/dra72-evm.dts +++ b/arch/arm/boot/dts/dra72-evm.dts | |||
@@ -9,12 +9,18 @@ | |||
9 | / { | 9 | / { |
10 | model = "TI DRA722"; | 10 | model = "TI DRA722"; |
11 | 11 | ||
12 | aliases { | ||
13 | display0 = &hdmi0; | ||
14 | sound1 = &hdmi; | ||
15 | i2c7 = &disp_ser; | ||
16 | }; | ||
17 | |||
12 | memory { | 18 | memory { |
13 | device_type = "memory"; | 19 | device_type = "memory"; |
14 | reg = <0x0 0x80000000 0x0 0x40000000>; /* 1024 MB */ | 20 | reg = <0x0 0x80000000 0x0 0x40000000>; /* 1024 MB */ |
15 | }; | 21 | }; |
16 | 22 | ||
17 | reserved-memory { | 23 | reserved_mem: reserved-memory { |
18 | #address-cells = <2>; | 24 | #address-cells = <2>; |
19 | #size-cells = <2>; | 25 | #size-cells = <2>; |
20 | ranges; | 26 | ranges; |
@@ -260,3 +266,18 @@ | |||
260 | status = "okay"; | 266 | status = "okay"; |
261 | memory-region = <&dsp1_cma_pool>; | 267 | memory-region = <&dsp1_cma_pool>; |
262 | }; | 268 | }; |
269 | |||
270 | video_in: &vin2a { | ||
271 | status = "okay"; | ||
272 | endpoint@0 { | ||
273 | slave-mode; | ||
274 | remote-endpoint = <&onboardLI>; | ||
275 | }; | ||
276 | }; | ||
277 | |||
278 | #include "dra7xx-jamr3.dtsi" | ||
279 | &tvp_5158{ | ||
280 | mux-gpios = <&pcf_hdmi 2 GPIO_ACTIVE_LOW>, /*VIN2_S0*/ | ||
281 | <&pcf_jamr3_21 8 GPIO_ACTIVE_LOW>, /*SEL_TVP_FPD*/ | ||
282 | <&pcf_hdmi 6 GPIO_ACTIVE_HIGH>; /*VIN2_S2*/ | ||
283 | }; | ||
diff --git a/arch/arm/boot/dts/dra76-evm-fpd-auo-g101evn01.0.dts b/arch/arm/boot/dts/dra76-evm-fpd-auo-g101evn01.0.dts new file mode 100644 index 000000000000..69983d70d1f4 --- /dev/null +++ b/arch/arm/boot/dts/dra76-evm-fpd-auo-g101evn01.0.dts | |||
@@ -0,0 +1,67 @@ | |||
1 | #include "dra76-evm.dts" | ||
2 | #include "dra7x-evm-fpd-auo-g101evn01.0.dtsi" | ||
3 | |||
4 | / { | ||
5 | aliases { | ||
6 | display0 = &fpd_disp; | ||
7 | display1 = &hdmi0; | ||
8 | }; | ||
9 | }; | ||
10 | |||
11 | &dss { | ||
12 | ports { | ||
13 | status = "ok"; | ||
14 | }; | ||
15 | }; | ||
16 | |||
17 | &disp_ser { | ||
18 | status = "ok"; | ||
19 | ranges = <0x0 0x2d>; | ||
20 | }; | ||
21 | |||
22 | /* Tie the end points of DSS and FPDLink together */ | ||
23 | &fpd_in { | ||
24 | remote-endpoint = <&dpi_out3>; | ||
25 | }; | ||
26 | |||
27 | &dpi_out3 { | ||
28 | remote-endpoint = <&fpd_in>; | ||
29 | }; | ||
30 | |||
31 | &lcd_fpd { | ||
32 | status = "ok"; | ||
33 | }; | ||
34 | |||
35 | /* U21 on the EVM */ | ||
36 | /* gpmc_ad_vid_s0: high: GPMC , low: VOUT3 */ | ||
37 | &pcf_gpio_21 { | ||
38 | p0 { | ||
39 | gpio-hog; | ||
40 | gpios = <0 GPIO_ACTIVE_HIGH>; | ||
41 | output-low; | ||
42 | line-name = "gpmc_ad_vid_s0"; | ||
43 | }; | ||
44 | }; | ||
45 | |||
46 | |||
47 | /* U110 on the EVM. For Rev A boards */ | ||
48 | /* | ||
49 | &pcf_hdmi { | ||
50 | p11 { | ||
51 | gpio-hog; | ||
52 | gpios = <11 GPIO_ACTIVE_HIGH>; | ||
53 | output-low; | ||
54 | line-name = "disp1_vpoc_onn"; | ||
55 | }; | ||
56 | }; | ||
57 | */ | ||
58 | |||
59 | /* For supplying power to the display via FPDLink */ | ||
60 | &gpio2 { | ||
61 | p2 { | ||
62 | gpio-hog; | ||
63 | gpios = <2 GPIO_ACTIVE_HIGH>; | ||
64 | output-low; | ||
65 | line-name = "disp1_vpoc_onn"; | ||
66 | }; | ||
67 | }; | ||
diff --git a/arch/arm/boot/dts/dra76-evm.dts b/arch/arm/boot/dts/dra76-evm.dts index db4fc1e99b1d..213f4b53f965 100644 --- a/arch/arm/boot/dts/dra76-evm.dts +++ b/arch/arm/boot/dts/dra76-evm.dts | |||
@@ -55,6 +55,10 @@ | |||
55 | }; | 55 | }; |
56 | }; | 56 | }; |
57 | 57 | ||
58 | aliases { | ||
59 | i2c7 = &disp_ser; | ||
60 | }; | ||
61 | |||
58 | vsys_12v0: fixedregulator-vsys12v0 { | 62 | vsys_12v0: fixedregulator-vsys12v0 { |
59 | /* main supply */ | 63 | /* main supply */ |
60 | compatible = "regulator-fixed"; | 64 | compatible = "regulator-fixed"; |
@@ -441,9 +445,35 @@ | |||
441 | phy-supply = <&ldo3_reg>; | 445 | phy-supply = <&ldo3_reg>; |
442 | }; | 446 | }; |
443 | 447 | ||
448 | &i2c3 { | ||
449 | disp_ser: serializer@0c { | ||
450 | compatible = "ti,ds90ub921q"; | ||
451 | reg = <0x0c>; | ||
452 | |||
453 | #address-cells = <1>; | ||
454 | #size-cells = <0>; | ||
455 | status = "disabled"; | ||
456 | }; | ||
457 | }; | ||
458 | |||
444 | &dss { | 459 | &dss { |
445 | status = "ok"; | 460 | status = "ok"; |
446 | vdda_video-supply = <&ldo5_reg>; | 461 | vdda_video-supply = <&ldo5_reg>; |
462 | |||
463 | ports { | ||
464 | #address-cells = <1>; | ||
465 | #size-cells = <0>; | ||
466 | |||
467 | status = "disabled"; | ||
468 | |||
469 | port@lcd3 { | ||
470 | reg = <2>; | ||
471 | |||
472 | dpi_out3: endpoint { | ||
473 | data-lines = <24>; | ||
474 | }; | ||
475 | }; | ||
476 | }; | ||
447 | }; | 477 | }; |
448 | 478 | ||
449 | &hdmi { | 479 | &hdmi { |
diff --git a/arch/arm/boot/dts/dra7x-evm-fpd-auo-g101evn01.0.dtsi b/arch/arm/boot/dts/dra7x-evm-fpd-auo-g101evn01.0.dtsi new file mode 100644 index 000000000000..c928be92c1ac --- /dev/null +++ b/arch/arm/boot/dts/dra7x-evm-fpd-auo-g101evn01.0.dtsi | |||
@@ -0,0 +1,107 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | / { | ||
10 | backlight { | ||
11 | compatible = "led-backlight"; | ||
12 | leds = <&backlight_led>; | ||
13 | brightness-levels = <0 2 38 74 110 146 182 218 255>; | ||
14 | default-brightness-level = <8>; | ||
15 | |||
16 | enable-gpios = <&pcf_display_board 0 GPIO_ACTIVE_LOW>; | ||
17 | }; | ||
18 | |||
19 | lcd_fpd: display { | ||
20 | compatible = "auo,g101evn01.0", "panel-dpi"; | ||
21 | |||
22 | label = "lcd_fpd"; | ||
23 | status = "disabled"; | ||
24 | |||
25 | panel-timing { | ||
26 | clock-frequency = <68930000>; | ||
27 | hactive = <1280>; | ||
28 | vactive = <800>; | ||
29 | |||
30 | hfront-porch = <48>; | ||
31 | hsync-len = <32>; | ||
32 | hback-porch = <48>; | ||
33 | |||
34 | vfront-porch = <4>; | ||
35 | vsync-len = <4>; | ||
36 | vback-porch = <8>; | ||
37 | |||
38 | hsync-active = <0>; | ||
39 | vsync-active = <0>; | ||
40 | de-active = <1>; | ||
41 | pixelclk-active = <1>; | ||
42 | }; | ||
43 | |||
44 | port { | ||
45 | fpd_in: endpoint { | ||
46 | }; | ||
47 | }; | ||
48 | }; | ||
49 | }; | ||
50 | |||
51 | &disp_ser { | ||
52 | |||
53 | /* | ||
54 | * 0x2c - deserializer | ||
55 | * 0x40 - TLC59108 | ||
56 | * 0x27 - PCF8575 | ||
57 | * 0x57 - EEPROM | ||
58 | * 0x14 - Goodix Touch Controller | ||
59 | * 0x28 - RF430CL330H | ||
60 | */ | ||
61 | |||
62 | disp_des: deserializer@2c { | ||
63 | #address-cells = <1>; | ||
64 | #size-cells = <0>; | ||
65 | compatible = "ti,ds90ub924q"; | ||
66 | reg = <0x2c>; | ||
67 | slave-mode; | ||
68 | }; | ||
69 | |||
70 | /* TLC chip for LCD panel power and backlight */ | ||
71 | fpd_disp: tlc59108@40 { | ||
72 | #address-cells = <1>; | ||
73 | #size-cells = <0>; | ||
74 | compatible = "ti,tlc59108"; | ||
75 | reg = <0x40>; | ||
76 | |||
77 | backlight_led: bl@2 { | ||
78 | label = "backlight"; | ||
79 | reg = <0x2>; | ||
80 | }; | ||
81 | }; | ||
82 | |||
83 | pcf_display_board: gpio@27 { | ||
84 | compatible = "nxp,pcf8575"; | ||
85 | reg = <0x27>; | ||
86 | gpio-controller; | ||
87 | #gpio-cells = <2>; | ||
88 | }; | ||
89 | |||
90 | touchscreen: goodix-gt9271@14 { | ||
91 | status = "okay"; | ||
92 | compatible = "goodix,gt9271"; | ||
93 | reg = <0x14>; | ||
94 | |||
95 | touchscreen-size-x = <1280>; | ||
96 | touchscreen-size-y = <800>; | ||
97 | touchscreen-inverted-y; | ||
98 | |||
99 | /* Reset gpio line is inverted before going to touch panel */ | ||
100 | reset-gpios = <&pcf_display_board 5 GPIO_ACTIVE_LOW>; | ||
101 | irq-gpios = <&pcf_display_board 6 GPIO_ACTIVE_HIGH>; | ||
102 | }; | ||
103 | |||
104 | /* Below two slaves on the I2C bus are not yet defined */ | ||
105 | /* ID EEPROM 0x57 */ | ||
106 | /* RF430CL330H 0x28 */ | ||
107 | }; | ||
diff --git a/arch/arm/boot/dts/dra7x-evm-fpd-lg.dtsi b/arch/arm/boot/dts/dra7x-evm-fpd-lg.dtsi new file mode 100644 index 000000000000..b4760b4efdad --- /dev/null +++ b/arch/arm/boot/dts/dra7x-evm-fpd-lg.dtsi | |||
@@ -0,0 +1,59 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <dt-bindings/gpio/gpio.h> | ||
10 | |||
11 | |||
12 | / { | ||
13 | lcd_fpd: display_fpd { | ||
14 | /* | ||
15 | * This is not really a dpi panel, but panel-dpi driver | ||
16 | * works as dummy panel driver. | ||
17 | */ | ||
18 | compatible = "lg,lp101wx2", "panel-dpi"; | ||
19 | |||
20 | label = "lcd_fpd"; | ||
21 | status = "disabled"; | ||
22 | |||
23 | panel-timing { | ||
24 | clock-frequency = <69300404>; | ||
25 | hactive = <1280>; | ||
26 | vactive = <800>; | ||
27 | |||
28 | hfront-porch = <48>; | ||
29 | hback-porch = <44>; | ||
30 | hsync-len = <32>; | ||
31 | |||
32 | vfront-porch = <4>; | ||
33 | vback-porch = <7>; | ||
34 | vsync-len = <12>; | ||
35 | |||
36 | hsync-active = <0>; | ||
37 | vsync-active = <0>; | ||
38 | de-active = <1>; | ||
39 | pixelclk-active = <0>; | ||
40 | }; | ||
41 | |||
42 | port { | ||
43 | fpd_in: endpoint { | ||
44 | }; | ||
45 | }; | ||
46 | }; | ||
47 | }; | ||
48 | |||
49 | &disp_ser { | ||
50 | disp_des: deserializer@2c { | ||
51 | compatible = "ti,ds90uh928q"; | ||
52 | reg = <0x2c>; | ||
53 | slave-mode; | ||
54 | }; | ||
55 | fpd_disp: tlc59108@1c { | ||
56 | compatible = "ti,tlc59108"; | ||
57 | reg = <0x1c>; | ||
58 | }; | ||
59 | }; | ||
diff --git a/arch/arm/boot/dts/dra7x-evm-lcd-lg.dtsi b/arch/arm/boot/dts/dra7x-evm-lcd-lg.dtsi index 71bc803c8282..23268b7a474f 100644 --- a/arch/arm/boot/dts/dra7x-evm-lcd-lg.dtsi +++ b/arch/arm/boot/dts/dra7x-evm-lcd-lg.dtsi | |||
@@ -50,7 +50,7 @@ | |||
50 | hsync-active = <0>; | 50 | hsync-active = <0>; |
51 | vsync-active = <0>; | 51 | vsync-active = <0>; |
52 | de-active = <1>; | 52 | de-active = <1>; |
53 | pixelclk-active = <1>; | 53 | pixelclk-active = <0>; |
54 | }; | 54 | }; |
55 | 55 | ||
56 | port { | 56 | port { |
@@ -83,6 +83,17 @@ | |||
83 | line-name = "LVDS_CLKSel"; | 83 | line-name = "LVDS_CLKSel"; |
84 | }; | 84 | }; |
85 | }; | 85 | }; |
86 | |||
87 | ldc3001:ldc3001@18 { | ||
88 | compatible = "lgphilips,ldc3001"; | ||
89 | status = "okay"; | ||
90 | reg = <0x18>; | ||
91 | interrupt-parent = <&gpio1>; | ||
92 | interrupts = <15 IRQ_TYPE_LEVEL_HIGH>; | ||
93 | max-touch-points = <10>; | ||
94 | res-x = <1280>; | ||
95 | res-y = <800>; | ||
96 | }; | ||
86 | }; | 97 | }; |
87 | 98 | ||
88 | &dss { | 99 | &dss { |
diff --git a/arch/arm/boot/dts/dra7xx-jamr3.dtsi b/arch/arm/boot/dts/dra7xx-jamr3.dtsi new file mode 100644 index 000000000000..894e97f93775 --- /dev/null +++ b/arch/arm/boot/dts/dra7xx-jamr3.dtsi | |||
@@ -0,0 +1,213 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/ | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <dt-bindings/clk/ti-dra7-atl.h> | ||
10 | |||
11 | / { | ||
12 | jamr3_sound { | ||
13 | compatible = "simple-audio-card"; | ||
14 | simple-audio-card,name = "DRA7xx-JAMR3"; | ||
15 | simple-audio-card,widgets = | ||
16 | "Line", "Line Out", | ||
17 | "Line", "Line In"; | ||
18 | simple-audio-card,routing = | ||
19 | "Line Out", "J3A LLOUT", | ||
20 | "Line Out", "J3A RLOUT", | ||
21 | "J3A LINE1L", "Line In", | ||
22 | "J3A LINE1R", "Line In"; | ||
23 | simple-audio-card,format = "dsp_b"; | ||
24 | simple-audio-card,bitclock-master = <&jamr3_sound_master>; | ||
25 | simple-audio-card,frame-master = <&jamr3_sound_master>; | ||
26 | simple-audio-card,bitclock-inversion; | ||
27 | |||
28 | jamr3_sound_master: simple-audio-card,cpu { | ||
29 | sound-dai = <&mcasp6>; | ||
30 | system-clock-frequency = <11289600>; | ||
31 | }; | ||
32 | |||
33 | simple-audio-card,codec { | ||
34 | sound-dai = <&tlv320aic3106a>; | ||
35 | clocks = <&atl_clkin1_ck>; | ||
36 | }; | ||
37 | }; | ||
38 | |||
39 | gatemp { | ||
40 | compatible = "hwspinlock-user"; | ||
41 | hwlocks = <&hwspinlock 0>, | ||
42 | <&hwspinlock 1>, | ||
43 | <&hwspinlock 2>, | ||
44 | <&hwspinlock 3>, | ||
45 | <&hwspinlock 4>, | ||
46 | <&hwspinlock 5>, | ||
47 | <&hwspinlock 6>, | ||
48 | <&hwspinlock 7>, | ||
49 | <&hwspinlock 8>, | ||
50 | <&hwspinlock 9>, | ||
51 | <&hwspinlock 10>, | ||
52 | <&hwspinlock 11>, | ||
53 | <&hwspinlock 12>, | ||
54 | <&hwspinlock 13>, | ||
55 | <&hwspinlock 14>, | ||
56 | <&hwspinlock 15>, | ||
57 | <&hwspinlock 16>, | ||
58 | <&hwspinlock 17>, | ||
59 | <&hwspinlock 18>, | ||
60 | <&hwspinlock 19>; | ||
61 | }; | ||
62 | |||
63 | sr0 { | ||
64 | compatible = "generic-uio"; | ||
65 | reg = <0x0 0xbfb00000 0x0 0x100000>; | ||
66 | }; | ||
67 | }; | ||
68 | |||
69 | &reserved_mem { | ||
70 | /* Required by cmem driver used by radio */ | ||
71 | cmem_radio: cmem@95400000 { | ||
72 | reg = <0x0 0x95400000 0x0 0x400000>; | ||
73 | no-map; | ||
74 | status = "okay"; | ||
75 | }; | ||
76 | |||
77 | dsp1_sr0: dsp1_sr0@bfb00000 { | ||
78 | reg = <0x0 0xbfb00000 0x0 0x100000>; | ||
79 | no-map; | ||
80 | status = "okay"; | ||
81 | }; | ||
82 | }; | ||
83 | |||
84 | &gpio6 { | ||
85 | p20 { | ||
86 | /* Radio reset GPIO */ | ||
87 | gpio-hog; | ||
88 | gpios = <1 GPIO_ACTIVE_LOW>; | ||
89 | output-low; | ||
90 | line-name = "radio_rst"; | ||
91 | }; | ||
92 | }; | ||
93 | |||
94 | &atl { | ||
95 | atl1 { | ||
96 | bws = <DRA7_ATL_WS_MCASP2_FSX>; | ||
97 | aws = <DRA7_ATL_WS_MCASP6_FSX>; | ||
98 | }; | ||
99 | }; | ||
100 | |||
101 | &mcasp2 { | ||
102 | assigned-clocks = <&mcasp2_ahclkx_mux>; | ||
103 | assigned-clock-parents = <&atl_clkin2_ck>; | ||
104 | |||
105 | status = "okay"; | ||
106 | |||
107 | op-mode = <0>; /* MCASP_IIS_MODE */ | ||
108 | tdm-slots = <2>; | ||
109 | /* 8 serializers */ | ||
110 | serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */ | ||
111 | 2 0 0 0 0 0 0 0 | ||
112 | >; | ||
113 | shared-dai; | ||
114 | }; | ||
115 | |||
116 | &mcasp6 { | ||
117 | #sound-dai-cells = <0>; | ||
118 | assigned-clocks = <&mcasp6_ahclkx_mux>; | ||
119 | assigned-clock-parents = <&atl_clkin1_ck>; | ||
120 | |||
121 | status = "okay"; | ||
122 | |||
123 | op-mode = <0>; /* MCASP_IIS_MODE */ | ||
124 | tdm-slots = <2>; | ||
125 | /* 4 serializer */ | ||
126 | serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */ | ||
127 | 1 2 0 0 | ||
128 | >; | ||
129 | tx-num-evt = <32>; | ||
130 | rx-num-evt = <32>; | ||
131 | shared-dai; | ||
132 | }; | ||
133 | |||
134 | &i2c4 { | ||
135 | status = "okay"; | ||
136 | clock-frequency = <400000>; | ||
137 | |||
138 | pcf_jamr3_21: pcf8575@21 { | ||
139 | compatible = "nxp,pcf8575"; | ||
140 | reg = <0x21>; | ||
141 | gpio-controller; | ||
142 | #gpio-cells = <2>; | ||
143 | }; | ||
144 | }; | ||
145 | |||
146 | &i2c_p3_exp { | ||
147 | tlv320aic3106a: tlv320aic3106@18 { | ||
148 | #sound-dai-cells = <0>; | ||
149 | compatible = "ti,tlv320aic3106"; | ||
150 | reg = <0x18>; | ||
151 | adc-settle-ms = <40>; | ||
152 | ai3x-micbias-vg = <1>; /* 2.0V */ | ||
153 | name-prefix = "J3A"; | ||
154 | status = "okay"; | ||
155 | |||
156 | /* Regulators */ | ||
157 | AVDD-supply = <&evm_3v3_sw>; | ||
158 | IOVDD-supply = <&evm_3v3_sw>; | ||
159 | DRVDD-supply = <&evm_3v3_sw>; | ||
160 | DVDD-supply = <&aic_dvdd>; | ||
161 | }; | ||
162 | |||
163 | tlv320aic3106b: tlv320aic3106@19 { | ||
164 | #sound-dai-cells = <0>; | ||
165 | compatible = "ti,tlv320aic3106"; | ||
166 | reg = <0x19>; | ||
167 | adc-settle-ms = <40>; | ||
168 | ai3x-micbias-vg = <1>; /* 2.0V */ | ||
169 | name-prefix = "J3B"; | ||
170 | status = "okay"; | ||
171 | |||
172 | /* Regulators */ | ||
173 | AVDD-supply = <&evm_3v3_sw>; | ||
174 | IOVDD-supply = <&evm_3v3_sw>; | ||
175 | DRVDD-supply = <&evm_3v3_sw>; | ||
176 | DVDD-supply = <&aic_dvdd>; | ||
177 | }; | ||
178 | |||
179 | tlv320aic3106c: tlv320aic3106@1a { | ||
180 | #sound-dai-cells = <0>; | ||
181 | compatible = "ti,tlv320aic3106"; | ||
182 | reg = <0x1a>; | ||
183 | adc-settle-ms = <40>; | ||
184 | ai3x-micbias-vg = <1>; /* 2.0V */ | ||
185 | name-prefix = "J3C"; | ||
186 | status = "okay"; | ||
187 | |||
188 | /* Regulators */ | ||
189 | AVDD-supply = <&evm_3v3_sw>; | ||
190 | IOVDD-supply = <&evm_3v3_sw>; | ||
191 | DRVDD-supply = <&evm_3v3_sw>; | ||
192 | DVDD-supply = <&aic_dvdd>; | ||
193 | }; | ||
194 | |||
195 | tvp_5158: tvp5158@58 { | ||
196 | compatible= "ti,tvp5158"; | ||
197 | reg = <0x58>; | ||
198 | |||
199 | port { | ||
200 | tvp_decoder: endpoint@0 { | ||
201 | pclk-sample = <0>; | ||
202 | channels = <0 2 4 6>; | ||
203 | }; | ||
204 | }; | ||
205 | }; | ||
206 | }; | ||
207 | |||
208 | &video_in { | ||
209 | endpoint { | ||
210 | slave-mode; | ||
211 | remote-endpoint = <&tvp_decoder>; | ||
212 | }; | ||
213 | }; | ||
diff --git a/arch/arm/boot/dts/dra7xx-vision.dtsi b/arch/arm/boot/dts/dra7xx-vision.dtsi new file mode 100644 index 000000000000..f593a68c8777 --- /dev/null +++ b/arch/arm/boot/dts/dra7xx-vision.dtsi | |||
@@ -0,0 +1,306 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Uncomment this define to enable IMI camera support | ||
11 | * #define VISION_IMI2_CAMERA | ||
12 | */ | ||
13 | / { | ||
14 | aliases { | ||
15 | i2c11 = &lvds_des1; | ||
16 | i2c12 = &lvds_des2; | ||
17 | i2c13 = &lvds_des3; | ||
18 | i2c14 = &lvds_des4; | ||
19 | i2c15 = &lvds_des5; | ||
20 | i2c16 = &lvds_des6; | ||
21 | }; | ||
22 | }; | ||
23 | |||
24 | &i2cexp { | ||
25 | |||
26 | ovcam_fc: ov10635@30 { | ||
27 | compatible = "ovti,ov10635"; | ||
28 | reg = <0x30>; | ||
29 | |||
30 | port { | ||
31 | ovcam: endpoint { | ||
32 | hsync-active = <1>; | ||
33 | vsync-active = <1>; | ||
34 | pclk-sample = <1>; | ||
35 | }; | ||
36 | }; | ||
37 | }; | ||
38 | |||
39 | /* | ||
40 | * These are I/O expanders which drive some signals of the deserializer | ||
41 | * Each 16bit I/O expander drives two deserializers | ||
42 | * The mapping of I/O expanders and deserializer is as follows:- | ||
43 | * I/O Expander | Deserializer | ||
44 | * -------------+---------------- | ||
45 | * mcp_ioexp1(0x27) | lvds_des1(0x60) | ||
46 | * mcp_ioexp1(0x27) | lvds_des2(0x64) | ||
47 | * mcp_ioexp2(0x21) | lvds_des3(0x68) | ||
48 | * mcp_ioexp2(0x21) | lvds_des4(0x6c) | ||
49 | * mcp_ioexp3(0x25) | lvds_des5(0x61) | ||
50 | * mcp_ioexp4(0x25) | lvds_des6(0x69) | ||
51 | */ | ||
52 | mcp_ioexp1: ioexp@27 { | ||
53 | compatible = "microchip,mcp23017"; | ||
54 | reg=<0x27>; | ||
55 | gpio-controller; | ||
56 | #gpio-cells = <2>; | ||
57 | |||
58 | init-dir = <0x0000>; | ||
59 | #ifdef VISION_IMI2_CAMERA | ||
60 | init-val = <0x6B6B>; | ||
61 | #else | ||
62 | init-val = <0x6363>; | ||
63 | #endif | ||
64 | /* 15:pdb, 14:sel, 13:oen, 12:bisten, 11:gpio0, 10-8:mode | ||
65 | * 7:pdb, 6:sel, 5:oen, 4:bisten, 3:gpio0, 2-0:mode | ||
66 | */ | ||
67 | }; | ||
68 | |||
69 | mcp_ioexp2: ioexp@21 { | ||
70 | compatible = "microchip,mcp23017"; | ||
71 | reg=<0x21>; | ||
72 | gpio-controller; | ||
73 | #gpio-cells = <2>; | ||
74 | |||
75 | init-dir = <0x0000>; | ||
76 | #ifdef VISION_IMI2_CAMERA | ||
77 | init-val = <0x6B6B>; | ||
78 | #else | ||
79 | init-val = <0x6363>; | ||
80 | #endif | ||
81 | /* 15:pdb, 14:sel, 13:oen, 12:bisten, 11:gpio0, 10-8:mode | ||
82 | * 7:pdb, 6:sel, 5:oen, 4:bisten, 3:gpio0, 2-0:mode | ||
83 | */ | ||
84 | }; | ||
85 | |||
86 | mcp_ioexp3: ioexp@25 { | ||
87 | compatible = "microchip,mcp23017"; | ||
88 | reg=<0x25>; | ||
89 | gpio-controller; | ||
90 | #gpio-cells = <2>; | ||
91 | |||
92 | init-dir = <0x0000>; | ||
93 | #ifdef VISION_IMI2_CAMERA | ||
94 | init-val = <0x6B6B>; | ||
95 | #else | ||
96 | init-val = <0x6363>; | ||
97 | #endif | ||
98 | /* 15:pdb, 14:sel, 13:oen, 12:bisten, 11:gpio0, 10-8:mode | ||
99 | * 7:pdb, 6:sel, 5:oen, 4:bisten, 3:gpio0, 2-0:mode | ||
100 | */ | ||
101 | }; | ||
102 | |||
103 | lvds_des1: deserializer@60 { | ||
104 | compatible = "ti,ds90ub914aq"; | ||
105 | reg = <0x60>; | ||
106 | |||
107 | gpios = <&mcp_ioexp1 7 0>; /* pdb */ | ||
108 | |||
109 | #address-cells = <1>; | ||
110 | #size-cells = <0>; | ||
111 | }; | ||
112 | |||
113 | lvds_des2: deserializer@64 { | ||
114 | compatible = "ti,ds90ub914aq"; | ||
115 | reg = <0x64>; | ||
116 | |||
117 | gpios = <&mcp_ioexp1 15 0>; /* pdb */ | ||
118 | |||
119 | #address-cells = <1>; | ||
120 | #size-cells = <0>; | ||
121 | }; | ||
122 | |||
123 | lvds_des3: deserializer@68 { | ||
124 | compatible = "ti,ds90ub914aq"; | ||
125 | reg = <0x68>; | ||
126 | |||
127 | gpios = <&mcp_ioexp2 7 0>; /* pdb */ | ||
128 | |||
129 | #address-cells = <1>; | ||
130 | #size-cells = <0>; | ||
131 | }; | ||
132 | |||
133 | lvds_des4: deserializer@6c { | ||
134 | compatible = "ti,ds90ub914aq"; | ||
135 | reg = <0x6c>; | ||
136 | |||
137 | gpios = <&mcp_ioexp2 15 0>; /* pdb */ | ||
138 | |||
139 | #address-cells = <1>; | ||
140 | #size-cells = <0>; | ||
141 | }; | ||
142 | |||
143 | lvds_des5: deserializer@61 { | ||
144 | compatible = "ti,ds90ub914aq"; | ||
145 | reg = <0x61>; | ||
146 | |||
147 | gpios = <&mcp_ioexp3 7 0>; /* pdb */ | ||
148 | |||
149 | #address-cells = <1>; | ||
150 | #size-cells = <0>; | ||
151 | }; | ||
152 | |||
153 | lvds_des6: deserializer@69 { | ||
154 | compatible = "ti,ds90ub914aq"; | ||
155 | reg = <0x69>; | ||
156 | |||
157 | gpios = <&mcp_ioexp3 15 0>; /* pdb */ | ||
158 | |||
159 | #address-cells = <1>; | ||
160 | #size-cells = <0>; | ||
161 | }; | ||
162 | }; | ||
163 | |||
164 | &lvds_des1 { | ||
165 | ranges = <0x58 0x74>, | ||
166 | <0x30 0x38>; | ||
167 | |||
168 | lvds_ser1: serializer@74 { | ||
169 | compatible = "ti,ds90ub913aq"; | ||
170 | reg = <0x58>; | ||
171 | slave-mode; | ||
172 | }; | ||
173 | |||
174 | ovcam1: ov10635@38 { | ||
175 | compatible = "ovti,ov10635"; | ||
176 | reg = <0x30>; | ||
177 | |||
178 | port { | ||
179 | cam1: endpoint { | ||
180 | hsync-active = <1>; | ||
181 | vsync-active = <1>; | ||
182 | pclk-sample = <0>; | ||
183 | }; | ||
184 | }; | ||
185 | }; | ||
186 | }; | ||
187 | |||
188 | &lvds_des2 { | ||
189 | ranges = <0x58 0x75>, | ||
190 | <0x30 0x39>; | ||
191 | |||
192 | lvds_ser2: serializer@75 { | ||
193 | compatible = "ti,ds90ub913aq"; | ||
194 | reg = <0x58>; | ||
195 | slave-mode; | ||
196 | }; | ||
197 | |||
198 | ovcam2: ov10635@39 { | ||
199 | compatible = "ovti,ov10635"; | ||
200 | reg = <0x30>; | ||
201 | |||
202 | port { | ||
203 | cam2: endpoint { | ||
204 | hsync-active = <1>; | ||
205 | vsync-active = <1>; | ||
206 | pclk-sample = <0>; | ||
207 | }; | ||
208 | }; | ||
209 | }; | ||
210 | }; | ||
211 | |||
212 | &lvds_des3 { | ||
213 | ranges = <0x58 0x76>, | ||
214 | <0x30 0x3a>; | ||
215 | |||
216 | lvds_ser3: serializer@76 { | ||
217 | compatible = "ti,ds90ub913aq"; | ||
218 | reg = <0x58>; | ||
219 | slave-mode; | ||
220 | }; | ||
221 | |||
222 | ovcam3: ov10635@3a { | ||
223 | compatible = "ovti,ov10635"; | ||
224 | reg = <0x30>; | ||
225 | |||
226 | port { | ||
227 | cam3: endpoint { | ||
228 | hsync-active = <1>; | ||
229 | vsync-active = <1>; | ||
230 | pclk-sample = <0>; | ||
231 | }; | ||
232 | }; | ||
233 | }; | ||
234 | }; | ||
235 | |||
236 | &lvds_des4 { | ||
237 | ranges = <0x58 0x77>, | ||
238 | <0x30 0x3b>; | ||
239 | |||
240 | lvds_ser4: serializer@77 { | ||
241 | compatible = "ti,ds90ub913aq"; | ||
242 | reg = <0x58>; | ||
243 | slave-mode; | ||
244 | }; | ||
245 | |||
246 | ovcam4: ov10635@3b { | ||
247 | compatible = "ovti,ov10635"; | ||
248 | reg = <0x30>; | ||
249 | |||
250 | port { | ||
251 | cam4: endpoint { | ||
252 | hsync-active = <1>; | ||
253 | vsync-active = <1>; | ||
254 | pclk-sample = <0>; | ||
255 | }; | ||
256 | }; | ||
257 | }; | ||
258 | }; | ||
259 | |||
260 | &lvds_des5 { | ||
261 | ranges = <0x58 0x78>, | ||
262 | <0x30 0x3c>; | ||
263 | |||
264 | lvds_ser5: serializer@78 { | ||
265 | compatible = "ti,ds90ub913aq"; | ||
266 | reg = <0x58>; | ||
267 | slave-mode; | ||
268 | }; | ||
269 | |||
270 | ovcam5: ov10635@3c { | ||
271 | compatible = "ovti,ov10635"; | ||
272 | reg = <0x30>; | ||
273 | |||
274 | port { | ||
275 | cam5: endpoint { | ||
276 | hsync-active = <1>; | ||
277 | vsync-active = <1>; | ||
278 | pclk-sample = <0>; | ||
279 | }; | ||
280 | }; | ||
281 | }; | ||
282 | }; | ||
283 | |||
284 | &lvds_des6 { | ||
285 | ranges = <0x58 0x79>, | ||
286 | <0x30 0x3d>; | ||
287 | |||
288 | lvds_ser6: serializer@79 { | ||
289 | compatible = "ti,ds90ub913aq"; | ||
290 | reg = <0x58>; | ||
291 | slave-mode; | ||
292 | }; | ||
293 | |||
294 | ovcam6: ov10635@3d { | ||
295 | compatible = "ovti,ov10635"; | ||
296 | reg = <0x30>; | ||
297 | |||
298 | port { | ||
299 | cam6: endpoint { | ||
300 | hsync-active = <1>; | ||
301 | vsync-active = <1>; | ||
302 | pclk-sample = <0>; | ||
303 | }; | ||
304 | }; | ||
305 | }; | ||
306 | }; | ||
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index b91a2d17a521..389133ce0139 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h | |||
@@ -15,6 +15,7 @@ | |||
15 | 15 | ||
16 | #define DMA_ERROR_CODE (~(dma_addr_t)0x0) | 16 | #define DMA_ERROR_CODE (~(dma_addr_t)0x0) |
17 | extern struct dma_map_ops arm_dma_ops; | 17 | extern struct dma_map_ops arm_dma_ops; |
18 | extern struct dma_map_ops arm_dma_m_ops; | ||
18 | extern struct dma_map_ops arm_coherent_dma_ops; | 19 | extern struct dma_map_ops arm_coherent_dma_ops; |
19 | 20 | ||
20 | static inline struct dma_map_ops *__generic_dma_ops(struct device *dev) | 21 | static inline struct dma_map_ops *__generic_dma_ops(struct device *dev) |
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 534a60ae282e..9bfd334f6e9b 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c | |||
@@ -145,6 +145,26 @@ struct dma_map_ops arm_dma_ops = { | |||
145 | }; | 145 | }; |
146 | EXPORT_SYMBOL(arm_dma_ops); | 146 | EXPORT_SYMBOL(arm_dma_ops); |
147 | 147 | ||
148 | static void *arm_dma_malloc(struct device *dev, size_t size, dma_addr_t *handle, | ||
149 | gfp_t gfp, struct dma_attrs *attrs); | ||
150 | |||
151 | struct dma_map_ops arm_dma_m_ops = { | ||
152 | .alloc = arm_dma_malloc, | ||
153 | .free = arm_dma_free, | ||
154 | .mmap = arm_dma_mmap, | ||
155 | .get_sgtable = arm_dma_get_sgtable, | ||
156 | .map_page = arm_dma_map_page, | ||
157 | .unmap_page = arm_dma_unmap_page, | ||
158 | .map_sg = arm_dma_map_sg, | ||
159 | .unmap_sg = arm_dma_unmap_sg, | ||
160 | .sync_single_for_cpu = arm_dma_sync_single_for_cpu, | ||
161 | .sync_single_for_device = arm_dma_sync_single_for_device, | ||
162 | .sync_sg_for_cpu = arm_dma_sync_sg_for_cpu, | ||
163 | .sync_sg_for_device = arm_dma_sync_sg_for_device, | ||
164 | .set_dma_mask = arm_dma_set_mask, | ||
165 | }; | ||
166 | EXPORT_SYMBOL(arm_dma_m_ops); | ||
167 | |||
148 | static void *arm_coherent_dma_alloc(struct device *dev, size_t size, | 168 | static void *arm_coherent_dma_alloc(struct device *dev, size_t size, |
149 | dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs); | 169 | dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs); |
150 | static void arm_coherent_dma_free(struct device *dev, size_t size, void *cpu_addr, | 170 | static void arm_coherent_dma_free(struct device *dev, size_t size, void *cpu_addr, |
@@ -293,7 +313,8 @@ static void __dma_free_buffer(struct page *page, size_t size) | |||
293 | 313 | ||
294 | static void *__alloc_from_contiguous(struct device *dev, size_t size, | 314 | static void *__alloc_from_contiguous(struct device *dev, size_t size, |
295 | pgprot_t prot, struct page **ret_page, | 315 | pgprot_t prot, struct page **ret_page, |
296 | const void *caller, bool want_vaddr); | 316 | const void *caller, bool want_vaddr, |
317 | bool zero); | ||
297 | 318 | ||
298 | static void *__alloc_remap_buffer(struct device *dev, size_t size, gfp_t gfp, | 319 | static void *__alloc_remap_buffer(struct device *dev, size_t size, gfp_t gfp, |
299 | pgprot_t prot, struct page **ret_page, | 320 | pgprot_t prot, struct page **ret_page, |
@@ -361,7 +382,8 @@ static int __init atomic_pool_init(void) | |||
361 | 382 | ||
362 | if (dev_get_cma_area(NULL)) | 383 | if (dev_get_cma_area(NULL)) |
363 | ptr = __alloc_from_contiguous(NULL, atomic_pool_size, prot, | 384 | ptr = __alloc_from_contiguous(NULL, atomic_pool_size, prot, |
364 | &page, atomic_pool_init, true); | 385 | &page, atomic_pool_init, true, |
386 | true); | ||
365 | else | 387 | else |
366 | ptr = __alloc_remap_buffer(NULL, atomic_pool_size, gfp, prot, | 388 | ptr = __alloc_remap_buffer(NULL, atomic_pool_size, gfp, prot, |
367 | &page, atomic_pool_init, true); | 389 | &page, atomic_pool_init, true); |
@@ -530,7 +552,8 @@ static int __free_from_pool(void *start, size_t size) | |||
530 | 552 | ||
531 | static void *__alloc_from_contiguous(struct device *dev, size_t size, | 553 | static void *__alloc_from_contiguous(struct device *dev, size_t size, |
532 | pgprot_t prot, struct page **ret_page, | 554 | pgprot_t prot, struct page **ret_page, |
533 | const void *caller, bool want_vaddr) | 555 | const void *caller, bool want_vaddr, |
556 | bool zero) | ||
534 | { | 557 | { |
535 | unsigned long order = get_order(size); | 558 | unsigned long order = get_order(size); |
536 | size_t count = size >> PAGE_SHIFT; | 559 | size_t count = size >> PAGE_SHIFT; |
@@ -541,7 +564,8 @@ static void *__alloc_from_contiguous(struct device *dev, size_t size, | |||
541 | if (!page) | 564 | if (!page) |
542 | return NULL; | 565 | return NULL; |
543 | 566 | ||
544 | __dma_clear_buffer(page, size); | 567 | if (zero) |
568 | __dma_clear_buffer(page, size); | ||
545 | 569 | ||
546 | if (!want_vaddr) | 570 | if (!want_vaddr) |
547 | goto out; | 571 | goto out; |
@@ -614,7 +638,8 @@ static void *__alloc_simple_buffer(struct device *dev, size_t size, gfp_t gfp, | |||
614 | 638 | ||
615 | static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, | 639 | static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, |
616 | gfp_t gfp, pgprot_t prot, bool is_coherent, | 640 | gfp_t gfp, pgprot_t prot, bool is_coherent, |
617 | struct dma_attrs *attrs, const void *caller) | 641 | struct dma_attrs *attrs, const void *caller, |
642 | bool zero) | ||
618 | { | 643 | { |
619 | u64 mask = get_coherent_dma_mask(dev); | 644 | u64 mask = get_coherent_dma_mask(dev); |
620 | struct page *page = NULL; | 645 | struct page *page = NULL; |
@@ -653,7 +678,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, | |||
653 | addr = __alloc_simple_buffer(dev, size, gfp, &page); | 678 | addr = __alloc_simple_buffer(dev, size, gfp, &page); |
654 | else if (dev_get_cma_area(dev) && (gfp & __GFP_DIRECT_RECLAIM)) | 679 | else if (dev_get_cma_area(dev) && (gfp & __GFP_DIRECT_RECLAIM)) |
655 | addr = __alloc_from_contiguous(dev, size, prot, &page, | 680 | addr = __alloc_from_contiguous(dev, size, prot, &page, |
656 | caller, want_vaddr); | 681 | caller, want_vaddr, zero); |
657 | else if (is_coherent) | 682 | else if (is_coherent) |
658 | addr = __alloc_simple_buffer(dev, size, gfp, &page); | 683 | addr = __alloc_simple_buffer(dev, size, gfp, &page); |
659 | else if (!gfpflags_allow_blocking(gfp)) | 684 | else if (!gfpflags_allow_blocking(gfp)) |
@@ -678,14 +703,30 @@ void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, | |||
678 | pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL); | 703 | pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL); |
679 | 704 | ||
680 | return __dma_alloc(dev, size, handle, gfp, prot, false, | 705 | return __dma_alloc(dev, size, handle, gfp, prot, false, |
681 | attrs, __builtin_return_address(0)); | 706 | attrs, __builtin_return_address(0), |
707 | true); | ||
682 | } | 708 | } |
683 | 709 | ||
710 | /* | ||
711 | * Same as arm_dma_alloc except don't zero memory on alloc | ||
712 | */ | ||
713 | void *arm_dma_malloc(struct device *dev, size_t size, dma_addr_t *handle, | ||
714 | gfp_t gfp, struct dma_attrs *attrs) | ||
715 | { | ||
716 | pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL); | ||
717 | |||
718 | return __dma_alloc(dev, size, handle, gfp, prot, false, | ||
719 | attrs, __builtin_return_address(0), | ||
720 | false); | ||
721 | } | ||
722 | |||
723 | |||
684 | static void *arm_coherent_dma_alloc(struct device *dev, size_t size, | 724 | static void *arm_coherent_dma_alloc(struct device *dev, size_t size, |
685 | dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs) | 725 | dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs) |
686 | { | 726 | { |
687 | return __dma_alloc(dev, size, handle, gfp, PAGE_KERNEL, true, | 727 | return __dma_alloc(dev, size, handle, gfp, PAGE_KERNEL, true, |
688 | attrs, __builtin_return_address(0)); | 728 | attrs, __builtin_return_address(0), |
729 | true); | ||
689 | } | 730 | } |
690 | 731 | ||
691 | static int __arm_dma_mmap(struct device *dev, struct vm_area_struct *vma, | 732 | static int __arm_dma_mmap(struct device *dev, struct vm_area_struct *vma, |
diff --git a/arch/arm/mm/proc-syms.c b/arch/arm/mm/proc-syms.c index 054b491ff764..778e32c97913 100644 --- a/arch/arm/mm/proc-syms.c +++ b/arch/arm/mm/proc-syms.c | |||
@@ -30,6 +30,7 @@ EXPORT_SYMBOL(__cpuc_flush_user_all); | |||
30 | EXPORT_SYMBOL(__cpuc_flush_user_range); | 30 | EXPORT_SYMBOL(__cpuc_flush_user_range); |
31 | EXPORT_SYMBOL(__cpuc_coherent_kern_range); | 31 | EXPORT_SYMBOL(__cpuc_coherent_kern_range); |
32 | EXPORT_SYMBOL(__cpuc_flush_dcache_area); | 32 | EXPORT_SYMBOL(__cpuc_flush_dcache_area); |
33 | EXPORT_SYMBOL(dmac_flush_range); | ||
33 | #else | 34 | #else |
34 | EXPORT_SYMBOL(cpu_cache); | 35 | EXPORT_SYMBOL(cpu_cache); |
35 | #endif | 36 | #endif |
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 4c48b52c4a7c..0f094594eed4 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c | |||
@@ -94,6 +94,13 @@ static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg, | |||
94 | 94 | ||
95 | static void omap_timer_restore_context(struct omap_dm_timer *timer) | 95 | static void omap_timer_restore_context(struct omap_dm_timer *timer) |
96 | { | 96 | { |
97 | /* | ||
98 | * Do not restore the context during late attach. Kernel data | ||
99 | * structure is not in sync with the register settings of the timer. | ||
100 | */ | ||
101 | if (timer->late_attach) | ||
102 | return; | ||
103 | |||
97 | omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, | 104 | omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, |
98 | timer->context.twer); | 105 | timer->context.twer); |
99 | omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, | 106 | omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, |
@@ -167,6 +174,14 @@ static int omap_dm_timer_prepare(struct omap_dm_timer *timer) | |||
167 | __omap_dm_timer_enable_posted(timer); | 174 | __omap_dm_timer_enable_posted(timer); |
168 | omap_dm_timer_disable(timer); | 175 | omap_dm_timer_disable(timer); |
169 | 176 | ||
177 | /* | ||
178 | * During late attach, do not set the timer source during prepare | ||
179 | * as the timer might be clocked from a different source. It will | ||
180 | * be set properly from remoteproc. | ||
181 | */ | ||
182 | if (timer->late_attach) | ||
183 | return 0; | ||
184 | |||
170 | return omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ); | 185 | return omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ); |
171 | } | 186 | } |
172 | 187 | ||
@@ -451,6 +466,16 @@ int omap_dm_timer_start(struct omap_dm_timer *timer) | |||
451 | 466 | ||
452 | /* Save the context */ | 467 | /* Save the context */ |
453 | timer->context.tclr = l; | 468 | timer->context.tclr = l; |
469 | |||
470 | /* | ||
471 | * Now that timer has been started, call pm_runtime_put_noidle to | ||
472 | * balance the pm_runtime device usage count to the proper value as | ||
473 | * the regular case, and reset the late_attach flag. | ||
474 | */ | ||
475 | if (timer->late_attach) | ||
476 | pm_runtime_put_noidle(&timer->pdev->dev); | ||
477 | timer->late_attach = 0; | ||
478 | |||
454 | return 0; | 479 | return 0; |
455 | } | 480 | } |
456 | EXPORT_SYMBOL_GPL(omap_dm_timer_start); | 481 | EXPORT_SYMBOL_GPL(omap_dm_timer_start); |
@@ -556,10 +581,18 @@ int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, | |||
556 | l |= OMAP_TIMER_CTRL_AR; | 581 | l |= OMAP_TIMER_CTRL_AR; |
557 | else | 582 | else |
558 | l &= ~OMAP_TIMER_CTRL_AR; | 583 | l &= ~OMAP_TIMER_CTRL_AR; |
559 | omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); | ||
560 | omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load); | ||
561 | 584 | ||
562 | omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0); | 585 | /* |
586 | * If late attach is enabled, do not modify the dmtimer registers. | ||
587 | * The registers would have been configured already. | ||
588 | */ | ||
589 | if (!timer->late_attach) { | ||
590 | omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); | ||
591 | omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load); | ||
592 | |||
593 | omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0); | ||
594 | } | ||
595 | |||
563 | /* Save the context */ | 596 | /* Save the context */ |
564 | timer->context.tclr = l; | 597 | timer->context.tclr = l; |
565 | timer->context.tldr = load; | 598 | timer->context.tldr = load; |
@@ -582,13 +615,21 @@ int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, | |||
582 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); | 615 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); |
583 | if (autoreload) { | 616 | if (autoreload) { |
584 | l |= OMAP_TIMER_CTRL_AR; | 617 | l |= OMAP_TIMER_CTRL_AR; |
585 | omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load); | 618 | /* |
619 | * If late attach is enabled, do not modify the dmtimer | ||
620 | * registers. The registers would have been configured | ||
621 | * already. | ||
622 | */ | ||
623 | if (!timer->late_attach) | ||
624 | omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, | ||
625 | load); | ||
586 | } else { | 626 | } else { |
587 | l &= ~OMAP_TIMER_CTRL_AR; | 627 | l &= ~OMAP_TIMER_CTRL_AR; |
588 | } | 628 | } |
589 | l |= OMAP_TIMER_CTRL_ST; | 629 | l |= OMAP_TIMER_CTRL_ST; |
590 | 630 | ||
591 | __omap_dm_timer_load_start(timer, l, load, timer->posted); | 631 | if (!timer->late_attach) |
632 | __omap_dm_timer_load_start(timer, l, load, timer->posted); | ||
592 | 633 | ||
593 | /* Save the context */ | 634 | /* Save the context */ |
594 | timer->context.tclr = l; | 635 | timer->context.tclr = l; |
@@ -807,6 +848,7 @@ static int omap_dm_timer_probe(struct platform_device *pdev) | |||
807 | const struct of_device_id *match; | 848 | const struct of_device_id *match; |
808 | const struct dmtimer_platform_data *pdata; | 849 | const struct dmtimer_platform_data *pdata; |
809 | int ret; | 850 | int ret; |
851 | struct property *prop; | ||
810 | 852 | ||
811 | match = of_match_device(of_match_ptr(omap_timer_match), dev); | 853 | match = of_match_device(of_match_ptr(omap_timer_match), dev); |
812 | pdata = match ? match->data : dev->platform_data; | 854 | pdata = match ? match->data : dev->platform_data; |
@@ -848,6 +890,17 @@ static int omap_dm_timer_probe(struct platform_device *pdev) | |||
848 | timer->capability |= OMAP_TIMER_HAS_PWM; | 890 | timer->capability |= OMAP_TIMER_HAS_PWM; |
849 | if (of_find_property(dev->of_node, "ti,timer-secure", NULL)) | 891 | if (of_find_property(dev->of_node, "ti,timer-secure", NULL)) |
850 | timer->capability |= OMAP_TIMER_SECURE; | 892 | timer->capability |= OMAP_TIMER_SECURE; |
893 | |||
894 | prop = of_find_property(dev->of_node, "ti,late-attach", NULL); | ||
895 | if (prop) { | ||
896 | timer->late_attach = 1; | ||
897 | /* | ||
898 | * Clear the late attach property in device tree for | ||
899 | * subsequent probes. | ||
900 | */ | ||
901 | if (of_remove_property(dev->of_node, prop)) | ||
902 | dev_err(dev, "Unable to remove late-attach property\n"); | ||
903 | } | ||
851 | } else { | 904 | } else { |
852 | timer->id = pdev->id; | 905 | timer->id = pdev->id; |
853 | timer->capability = pdata->timer_capability; | 906 | timer->capability = pdata->timer_capability; |
@@ -875,6 +928,14 @@ static int omap_dm_timer_probe(struct platform_device *pdev) | |||
875 | goto err_get_sync; | 928 | goto err_get_sync; |
876 | } | 929 | } |
877 | __omap_dm_timer_init_regs(timer); | 930 | __omap_dm_timer_init_regs(timer); |
931 | |||
932 | /* | ||
933 | * Increase the pm_runtime usage count and prevent kernel power | ||
934 | * management from idling or disabling the timer. | ||
935 | */ | ||
936 | if (timer->late_attach) | ||
937 | pm_runtime_get_noresume(dev); | ||
938 | |||
878 | pm_runtime_put(dev); | 939 | pm_runtime_put(dev); |
879 | } | 940 | } |
880 | 941 | ||
@@ -912,6 +973,12 @@ static int omap_dm_timer_remove(struct platform_device *pdev) | |||
912 | if (!strcmp(dev_name(&timer->pdev->dev), | 973 | if (!strcmp(dev_name(&timer->pdev->dev), |
913 | dev_name(&pdev->dev))) { | 974 | dev_name(&pdev->dev))) { |
914 | list_del(&timer->node); | 975 | list_del(&timer->node); |
976 | /* | ||
977 | * Reset device usage counter if late_attach is still | ||
978 | * set | ||
979 | */ | ||
980 | if (timer->late_attach) | ||
981 | pm_runtime_put_noidle(&timer->pdev->dev); | ||
915 | ret = 0; | 982 | ret = 0; |
916 | break; | 983 | break; |
917 | } | 984 | } |
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h index dd79f3005cdf..3f2653eca46c 100644 --- a/arch/arm/plat-omap/include/plat/dmtimer.h +++ b/arch/arm/plat-omap/include/plat/dmtimer.h | |||
@@ -122,6 +122,7 @@ struct omap_dm_timer { | |||
122 | u32 errata; | 122 | u32 errata; |
123 | struct platform_device *pdev; | 123 | struct platform_device *pdev; |
124 | struct list_head node; | 124 | struct list_head node; |
125 | u32 late_attach; | ||
125 | }; | 126 | }; |
126 | 127 | ||
127 | int omap_dm_timer_reserve_systimer(int id); | 128 | int omap_dm_timer_reserve_systimer(int id); |
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 5c74ad90a447..049335584e0c 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig | |||
@@ -581,6 +581,7 @@ source kernel/Kconfig.preempt | |||
581 | source kernel/Kconfig.hz | 581 | source kernel/Kconfig.hz |
582 | 582 | ||
583 | config ARCH_SUPPORTS_DEBUG_PAGEALLOC | 583 | config ARCH_SUPPORTS_DEBUG_PAGEALLOC |
584 | depends on !HIBERNATION | ||
584 | def_bool y | 585 | def_bool y |
585 | 586 | ||
586 | config ARCH_HAS_HOLES_MEMORYMODEL | 587 | config ARCH_HAS_HOLES_MEMORYMODEL |
@@ -630,6 +631,27 @@ config SECCOMP | |||
630 | and the task is only allowed to execute a few safe syscalls | 631 | and the task is only allowed to execute a few safe syscalls |
631 | defined by each seccomp mode. | 632 | defined by each seccomp mode. |
632 | 633 | ||
634 | config KEXEC | ||
635 | depends on PM_SLEEP_SMP | ||
636 | select KEXEC_CORE | ||
637 | bool "kexec system call" | ||
638 | ---help--- | ||
639 | kexec is a system call that implements the ability to shutdown your | ||
640 | current kernel, and to start another kernel. It is like a reboot | ||
641 | but it is independent of the system firmware. And like a reboot | ||
642 | you can start any kernel with it, not just Linux. | ||
643 | |||
644 | config CRASH_DUMP | ||
645 | bool "Build kdump crash kernel" | ||
646 | help | ||
647 | Generate crash dump after being started by kexec. This should | ||
648 | be normally only set in special crash dump kernels which are | ||
649 | loaded in the main kernel with kexec-tools into a specially | ||
650 | reserved region and then later executed after a crash by | ||
651 | kdump/kexec. | ||
652 | |||
653 | For more details see Documentation/kdump/kdump.txt | ||
654 | |||
633 | config XEN_DOM0 | 655 | config XEN_DOM0 |
634 | def_bool y | 656 | def_bool y |
635 | depends on XEN | 657 | depends on XEN |
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 79717faf2161..7dc5e58f7b7a 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig | |||
@@ -58,6 +58,8 @@ CONFIG_PREEMPT=y | |||
58 | CONFIG_KSM=y | 58 | CONFIG_KSM=y |
59 | CONFIG_TRANSPARENT_HUGEPAGE=y | 59 | CONFIG_TRANSPARENT_HUGEPAGE=y |
60 | CONFIG_CMA=y | 60 | CONFIG_CMA=y |
61 | CONFIG_KEXEC=y | ||
62 | CONFIG_CRASH_DUMP=y | ||
61 | CONFIG_CMDLINE="console=ttyAMA0" | 63 | CONFIG_CMDLINE="console=ttyAMA0" |
62 | # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set | 64 | # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set |
63 | CONFIG_COMPAT=y | 65 | CONFIG_COMPAT=y |
diff --git a/arch/arm64/include/asm/cacheflush.h b/arch/arm64/include/asm/cacheflush.h index 22dda613f9c9..22aabdeacc24 100644 --- a/arch/arm64/include/asm/cacheflush.h +++ b/arch/arm64/include/asm/cacheflush.h | |||
@@ -155,5 +155,6 @@ int set_memory_ro(unsigned long addr, int numpages); | |||
155 | int set_memory_rw(unsigned long addr, int numpages); | 155 | int set_memory_rw(unsigned long addr, int numpages); |
156 | int set_memory_x(unsigned long addr, int numpages); | 156 | int set_memory_x(unsigned long addr, int numpages); |
157 | int set_memory_nx(unsigned long addr, int numpages); | 157 | int set_memory_nx(unsigned long addr, int numpages); |
158 | int set_memory_valid(unsigned long addr, unsigned long size, int enable); | ||
158 | 159 | ||
159 | #endif | 160 | #endif |
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index 6818fbec44c6..8e1f826caf99 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h | |||
@@ -33,6 +33,7 @@ | |||
33 | #define ARM64_HAS_NO_HW_PREFETCH 8 | 33 | #define ARM64_HAS_NO_HW_PREFETCH 8 |
34 | #define ARM64_HAS_UAO 9 | 34 | #define ARM64_HAS_UAO 9 |
35 | #define ARM64_ALT_PAN_NOT_UAO 10 | 35 | #define ARM64_ALT_PAN_NOT_UAO 10 |
36 | |||
36 | #define ARM64_WORKAROUND_CAVIUM_27456 11 | 37 | #define ARM64_WORKAROUND_CAVIUM_27456 11 |
37 | #define ARM64_HAS_VIRT_HOST_EXTN 12 | 38 | #define ARM64_HAS_VIRT_HOST_EXTN 12 |
38 | #define ARM64_NCAPS 13 | 39 | #define ARM64_NCAPS 13 |
diff --git a/arch/arm64/include/asm/hardirq.h b/arch/arm64/include/asm/hardirq.h index 8740297dac77..1473fc2f7ab7 100644 --- a/arch/arm64/include/asm/hardirq.h +++ b/arch/arm64/include/asm/hardirq.h | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <linux/threads.h> | 20 | #include <linux/threads.h> |
21 | #include <asm/irq.h> | 21 | #include <asm/irq.h> |
22 | 22 | ||
23 | #define NR_IPI 6 | 23 | #define NR_IPI 7 |
24 | 24 | ||
25 | typedef struct { | 25 | typedef struct { |
26 | unsigned int __softirq_pending; | 26 | unsigned int __softirq_pending; |
diff --git a/arch/arm64/include/asm/kexec.h b/arch/arm64/include/asm/kexec.h new file mode 100644 index 000000000000..e17f0529a882 --- /dev/null +++ b/arch/arm64/include/asm/kexec.h | |||
@@ -0,0 +1,98 @@ | |||
1 | /* | ||
2 | * kexec for arm64 | ||
3 | * | ||
4 | * Copyright (C) Linaro. | ||
5 | * Copyright (C) Huawei Futurewei Technologies. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #ifndef _ARM64_KEXEC_H | ||
13 | #define _ARM64_KEXEC_H | ||
14 | |||
15 | /* Maximum physical address we can use pages from */ | ||
16 | |||
17 | #define KEXEC_SOURCE_MEMORY_LIMIT (-1UL) | ||
18 | |||
19 | /* Maximum address we can reach in physical address mode */ | ||
20 | |||
21 | #define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL) | ||
22 | |||
23 | /* Maximum address we can use for the control code buffer */ | ||
24 | |||
25 | #define KEXEC_CONTROL_MEMORY_LIMIT (-1UL) | ||
26 | |||
27 | #define KEXEC_CONTROL_PAGE_SIZE 4096 | ||
28 | |||
29 | #define KEXEC_ARCH KEXEC_ARCH_AARCH64 | ||
30 | |||
31 | #ifndef __ASSEMBLY__ | ||
32 | |||
33 | /** | ||
34 | * crash_setup_regs() - save registers for the panic kernel | ||
35 | * | ||
36 | * @newregs: registers are saved here | ||
37 | * @oldregs: registers to be saved (may be %NULL) | ||
38 | */ | ||
39 | |||
40 | static inline void crash_setup_regs(struct pt_regs *newregs, | ||
41 | struct pt_regs *oldregs) | ||
42 | { | ||
43 | if (oldregs) { | ||
44 | memcpy(newregs, oldregs, sizeof(*newregs)); | ||
45 | } else { | ||
46 | u64 tmp1, tmp2; | ||
47 | |||
48 | __asm__ __volatile__ ( | ||
49 | "stp x0, x1, [%2, #16 * 0]\n" | ||
50 | "stp x2, x3, [%2, #16 * 1]\n" | ||
51 | "stp x4, x5, [%2, #16 * 2]\n" | ||
52 | "stp x6, x7, [%2, #16 * 3]\n" | ||
53 | "stp x8, x9, [%2, #16 * 4]\n" | ||
54 | "stp x10, x11, [%2, #16 * 5]\n" | ||
55 | "stp x12, x13, [%2, #16 * 6]\n" | ||
56 | "stp x14, x15, [%2, #16 * 7]\n" | ||
57 | "stp x16, x17, [%2, #16 * 8]\n" | ||
58 | "stp x18, x19, [%2, #16 * 9]\n" | ||
59 | "stp x20, x21, [%2, #16 * 10]\n" | ||
60 | "stp x22, x23, [%2, #16 * 11]\n" | ||
61 | "stp x24, x25, [%2, #16 * 12]\n" | ||
62 | "stp x26, x27, [%2, #16 * 13]\n" | ||
63 | "stp x28, x29, [%2, #16 * 14]\n" | ||
64 | "mov %0, sp\n" | ||
65 | "stp x30, %0, [%2, #16 * 15]\n" | ||
66 | |||
67 | "/* faked current PSTATE */\n" | ||
68 | "mrs %0, CurrentEL\n" | ||
69 | "mrs %1, SPSEL\n" | ||
70 | "orr %0, %0, %1\n" | ||
71 | "mrs %1, DAIF\n" | ||
72 | "orr %0, %0, %1\n" | ||
73 | "mrs %1, NZCV\n" | ||
74 | "orr %0, %0, %1\n" | ||
75 | /* pc */ | ||
76 | "adr %1, 1f\n" | ||
77 | "1:\n" | ||
78 | "stp %1, %0, [%2, #16 * 16]\n" | ||
79 | : "=&r" (tmp1), "=&r" (tmp2) | ||
80 | : "r" (newregs) | ||
81 | : "memory" | ||
82 | ); | ||
83 | } | ||
84 | } | ||
85 | |||
86 | #if defined(CONFIG_KEXEC_CORE) && defined(CONFIG_HIBERNATION) | ||
87 | extern bool crash_is_nosave(unsigned long pfn); | ||
88 | extern void crash_prepare_suspend(void); | ||
89 | extern void crash_post_resume(void); | ||
90 | #else | ||
91 | static inline bool crash_is_nosave(unsigned long pfn) {return false; } | ||
92 | static inline void crash_prepare_suspend(void) {} | ||
93 | static inline void crash_post_resume(void) {} | ||
94 | #endif | ||
95 | |||
96 | #endif /* __ASSEMBLY__ */ | ||
97 | |||
98 | #endif | ||
diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h index 990124a67eeb..5472251c8e6c 100644 --- a/arch/arm64/include/asm/mmu.h +++ b/arch/arm64/include/asm/mmu.h | |||
@@ -33,7 +33,7 @@ extern void __iomem *early_io_map(phys_addr_t phys, unsigned long virt); | |||
33 | extern void init_mem_pgprot(void); | 33 | extern void init_mem_pgprot(void); |
34 | extern void create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys, | 34 | extern void create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys, |
35 | unsigned long virt, phys_addr_t size, | 35 | unsigned long virt, phys_addr_t size, |
36 | pgprot_t prot); | 36 | pgprot_t prot, bool allow_block_mappings); |
37 | extern void *fixmap_remap_fdt(phys_addr_t dt_phys); | 37 | extern void *fixmap_remap_fdt(phys_addr_t dt_phys); |
38 | 38 | ||
39 | #endif | 39 | #endif |
diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h index 2013a4dc5124..1d3ff7e4a6c2 100644 --- a/arch/arm64/include/asm/smp.h +++ b/arch/arm64/include/asm/smp.h | |||
@@ -16,6 +16,19 @@ | |||
16 | #ifndef __ASM_SMP_H | 16 | #ifndef __ASM_SMP_H |
17 | #define __ASM_SMP_H | 17 | #define __ASM_SMP_H |
18 | 18 | ||
19 | /* Values for secondary_data.status */ | ||
20 | |||
21 | #define CPU_MMU_OFF (-1) | ||
22 | #define CPU_BOOT_SUCCESS (0) | ||
23 | /* The cpu invoked ops->cpu_die, synchronise it with cpu_kill */ | ||
24 | #define CPU_KILL_ME (1) | ||
25 | /* The cpu couldn't die gracefully and is looping in the kernel */ | ||
26 | #define CPU_STUCK_IN_KERNEL (2) | ||
27 | /* Fatal system error detected by secondary CPU, crash the system */ | ||
28 | #define CPU_PANIC_KERNEL (3) | ||
29 | |||
30 | #ifndef __ASSEMBLY__ | ||
31 | |||
19 | #include <linux/threads.h> | 32 | #include <linux/threads.h> |
20 | #include <linux/cpumask.h> | 33 | #include <linux/cpumask.h> |
21 | #include <linux/thread_info.h> | 34 | #include <linux/thread_info.h> |
@@ -54,11 +67,17 @@ asmlinkage void secondary_start_kernel(void); | |||
54 | 67 | ||
55 | /* | 68 | /* |
56 | * Initial data for bringing up a secondary CPU. | 69 | * Initial data for bringing up a secondary CPU. |
70 | * @stack - sp for the secondary CPU | ||
71 | * @status - Result passed back from the secondary CPU to | ||
72 | * indicate failure. | ||
57 | */ | 73 | */ |
58 | struct secondary_data { | 74 | struct secondary_data { |
59 | void *stack; | 75 | void *stack; |
76 | long status; | ||
60 | }; | 77 | }; |
78 | |||
61 | extern struct secondary_data secondary_data; | 79 | extern struct secondary_data secondary_data; |
80 | extern long __early_cpu_boot_status; | ||
62 | extern void secondary_entry(void); | 81 | extern void secondary_entry(void); |
63 | 82 | ||
64 | extern void arch_send_call_function_single_ipi(int cpu); | 83 | extern void arch_send_call_function_single_ipi(int cpu); |
@@ -77,5 +96,38 @@ extern int __cpu_disable(void); | |||
77 | 96 | ||
78 | extern void __cpu_die(unsigned int cpu); | 97 | extern void __cpu_die(unsigned int cpu); |
79 | extern void cpu_die(void); | 98 | extern void cpu_die(void); |
99 | extern void cpu_die_early(void); | ||
100 | |||
101 | static inline void cpu_park_loop(void) | ||
102 | { | ||
103 | for (;;) { | ||
104 | wfe(); | ||
105 | wfi(); | ||
106 | } | ||
107 | } | ||
108 | |||
109 | static inline void update_cpu_boot_status(int val) | ||
110 | { | ||
111 | WRITE_ONCE(secondary_data.status, val); | ||
112 | /* Ensure the visibility of the status update */ | ||
113 | dsb(ishst); | ||
114 | } | ||
115 | |||
116 | /* | ||
117 | * If a secondary CPU enters the kernel but fails to come online, | ||
118 | * (e.g. due to mismatched features), and cannot exit the kernel, | ||
119 | * we increment cpus_stuck_in_kernel and leave the CPU in a | ||
120 | * quiesecent loop within the kernel text. The memory containing | ||
121 | * this loop must not be re-used for anything else as the 'stuck' | ||
122 | * core is executing it. | ||
123 | * | ||
124 | * This function is used to inhibit features like kexec and hibernate. | ||
125 | */ | ||
126 | bool cpus_are_stuck_in_kernel(void); | ||
127 | |||
128 | extern void smp_send_crash_stop(void); | ||
129 | extern bool smp_crash_stop_failed(void); | ||
130 | |||
131 | #endif /* ifndef __ASSEMBLY__ */ | ||
80 | 132 | ||
81 | #endif /* ifndef __ASM_SMP_H */ | 133 | #endif /* ifndef __ASM_SMP_H */ |
diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h index 06e6a5238c4c..e6c27b8ce311 100644 --- a/arch/arm64/include/asm/virt.h +++ b/arch/arm64/include/asm/virt.h | |||
@@ -34,6 +34,11 @@ | |||
34 | */ | 34 | */ |
35 | #define HVC_SET_VECTORS 1 | 35 | #define HVC_SET_VECTORS 1 |
36 | 36 | ||
37 | /* | ||
38 | * HVC_SOFT_RESTART - CPU soft reset, used by the cpu_soft_restart routine. | ||
39 | */ | ||
40 | #define HVC_SOFT_RESTART 2 | ||
41 | |||
37 | #define BOOT_CPU_MODE_EL1 (0xe11) | 42 | #define BOOT_CPU_MODE_EL1 (0xe11) |
38 | #define BOOT_CPU_MODE_EL2 (0xe12) | 43 | #define BOOT_CPU_MODE_EL2 (0xe12) |
39 | 44 | ||
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 4e8a30b7e949..01c0b3881f88 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile | |||
@@ -44,7 +44,9 @@ arm64-obj-$(CONFIG_ACPI) += acpi.o | |||
44 | arm64-obj-$(CONFIG_RANDOMIZE_BASE) += kaslr.o | 44 | arm64-obj-$(CONFIG_RANDOMIZE_BASE) += kaslr.o |
45 | arm64-obj-$(CONFIG_HIBERNATION) += hibernate.o hibernate-asm.o | 45 | arm64-obj-$(CONFIG_HIBERNATION) += hibernate.o hibernate-asm.o |
46 | arm64-obj-$(CONFIG_ARM64_ACPI_PARKING_PROTOCOL) += acpi_parking_protocol.o | 46 | arm64-obj-$(CONFIG_ARM64_ACPI_PARKING_PROTOCOL) += acpi_parking_protocol.o |
47 | arm64-obj-$(CONFIG_PARAVIRT) += paravirt.o | 47 | arm64-obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o \ |
48 | cpu-reset.o | ||
49 | arm64-obj-$(CONFIG_CRASH_DUMP) += crash_dump.o | ||
48 | 50 | ||
49 | obj-y += $(arm64-obj-y) vdso/ probes/ | 51 | obj-y += $(arm64-obj-y) vdso/ probes/ |
50 | obj-m += $(arm64-obj-m) | 52 | obj-m += $(arm64-obj-m) |
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c index 350c0e99fc6b..7a3f34b15fb0 100644 --- a/arch/arm64/kernel/asm-offsets.c +++ b/arch/arm64/kernel/asm-offsets.c | |||
@@ -124,6 +124,8 @@ int main(void) | |||
124 | DEFINE(TZ_MINWEST, offsetof(struct timezone, tz_minuteswest)); | 124 | DEFINE(TZ_MINWEST, offsetof(struct timezone, tz_minuteswest)); |
125 | DEFINE(TZ_DSTTIME, offsetof(struct timezone, tz_dsttime)); | 125 | DEFINE(TZ_DSTTIME, offsetof(struct timezone, tz_dsttime)); |
126 | BLANK(); | 126 | BLANK(); |
127 | DEFINE(CPU_BOOT_STACK, offsetof(struct secondary_data, stack)); | ||
128 | BLANK(); | ||
127 | #ifdef CONFIG_KVM_ARM_HOST | 129 | #ifdef CONFIG_KVM_ARM_HOST |
128 | DEFINE(VCPU_CONTEXT, offsetof(struct kvm_vcpu, arch.ctxt)); | 130 | DEFINE(VCPU_CONTEXT, offsetof(struct kvm_vcpu, arch.ctxt)); |
129 | DEFINE(CPU_GP_REGS, offsetof(struct kvm_cpu_context, gp_regs)); | 131 | DEFINE(CPU_GP_REGS, offsetof(struct kvm_cpu_context, gp_regs)); |
diff --git a/arch/arm64/kernel/cpu-reset.S b/arch/arm64/kernel/cpu-reset.S new file mode 100644 index 000000000000..65f42d257414 --- /dev/null +++ b/arch/arm64/kernel/cpu-reset.S | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | * CPU reset routines | ||
3 | * | ||
4 | * Copyright (C) 2001 Deep Blue Solutions Ltd. | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * Copyright (C) 2015 Huawei Futurewei Technologies. | ||
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 <linux/linkage.h> | ||
14 | #include <asm/assembler.h> | ||
15 | #include <asm/sysreg.h> | ||
16 | #include <asm/virt.h> | ||
17 | |||
18 | .text | ||
19 | .pushsection .idmap.text, "ax" | ||
20 | |||
21 | /* | ||
22 | * __cpu_soft_restart(el2_switch, entry, arg0, arg1, arg2) - Helper for | ||
23 | * cpu_soft_restart. | ||
24 | * | ||
25 | * @el2_switch: Flag to indicate a swich to EL2 is needed. | ||
26 | * @entry: Location to jump to for soft reset. | ||
27 | * arg0: First argument passed to @entry. | ||
28 | * arg1: Second argument passed to @entry. | ||
29 | * arg2: Third argument passed to @entry. | ||
30 | * | ||
31 | * Put the CPU into the same state as it would be if it had been reset, and | ||
32 | * branch to what would be the reset vector. It must be executed with the | ||
33 | * flat identity mapping. | ||
34 | */ | ||
35 | ENTRY(__cpu_soft_restart) | ||
36 | /* Clear sctlr_el1 flags. */ | ||
37 | mrs x12, sctlr_el1 | ||
38 | ldr x13, =SCTLR_ELx_FLAGS | ||
39 | bic x12, x12, x13 | ||
40 | msr sctlr_el1, x12 | ||
41 | isb | ||
42 | |||
43 | cbz x0, 1f // el2_switch? | ||
44 | mov x0, #HVC_SOFT_RESTART | ||
45 | hvc #0 // no return | ||
46 | |||
47 | 1: mov x18, x1 // entry | ||
48 | mov x0, x2 // arg0 | ||
49 | mov x1, x3 // arg1 | ||
50 | mov x2, x4 // arg2 | ||
51 | br x18 | ||
52 | ENDPROC(__cpu_soft_restart) | ||
53 | |||
54 | .popsection | ||
diff --git a/arch/arm64/kernel/cpu-reset.h b/arch/arm64/kernel/cpu-reset.h new file mode 100644 index 000000000000..d4e9ecb264f0 --- /dev/null +++ b/arch/arm64/kernel/cpu-reset.h | |||
@@ -0,0 +1,34 @@ | |||
1 | /* | ||
2 | * CPU reset routines | ||
3 | * | ||
4 | * Copyright (C) 2015 Huawei Futurewei Technologies. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef _ARM64_CPU_RESET_H | ||
12 | #define _ARM64_CPU_RESET_H | ||
13 | |||
14 | #include <asm/virt.h> | ||
15 | |||
16 | void __cpu_soft_restart(unsigned long el2_switch, unsigned long entry, | ||
17 | unsigned long arg0, unsigned long arg1, unsigned long arg2); | ||
18 | |||
19 | static inline void __noreturn cpu_soft_restart(unsigned long el2_switch, | ||
20 | unsigned long entry, unsigned long arg0, unsigned long arg1, | ||
21 | unsigned long arg2) | ||
22 | { | ||
23 | typeof(__cpu_soft_restart) *restart; | ||
24 | |||
25 | el2_switch = el2_switch && !is_kernel_in_hyp_mode() && | ||
26 | is_hyp_mode_available(); | ||
27 | restart = (void *)virt_to_phys(__cpu_soft_restart); | ||
28 | |||
29 | cpu_install_idmap(); | ||
30 | restart(el2_switch, entry, arg0, arg1, arg2); | ||
31 | unreachable(); | ||
32 | } | ||
33 | |||
34 | #endif | ||
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index cdf1dca64133..53fab76d3c39 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c | |||
@@ -895,28 +895,6 @@ static u64 __raw_read_system_reg(u32 sys_id) | |||
895 | } | 895 | } |
896 | 896 | ||
897 | /* | 897 | /* |
898 | * Park the CPU which doesn't have the capability as advertised | ||
899 | * by the system. | ||
900 | */ | ||
901 | static void fail_incapable_cpu(char *cap_type, | ||
902 | const struct arm64_cpu_capabilities *cap) | ||
903 | { | ||
904 | int cpu = smp_processor_id(); | ||
905 | |||
906 | pr_crit("CPU%d: missing %s : %s\n", cpu, cap_type, cap->desc); | ||
907 | /* Mark this CPU absent */ | ||
908 | set_cpu_present(cpu, 0); | ||
909 | |||
910 | /* Check if we can park ourselves */ | ||
911 | if (cpu_ops[cpu] && cpu_ops[cpu]->cpu_die) | ||
912 | cpu_ops[cpu]->cpu_die(cpu); | ||
913 | asm( | ||
914 | "1: wfe\n" | ||
915 | " wfi\n" | ||
916 | " b 1b"); | ||
917 | } | ||
918 | |||
919 | /* | ||
920 | * Run through the enabled system capabilities and enable() it on this CPU. | 898 | * Run through the enabled system capabilities and enable() it on this CPU. |
921 | * The capabilities were decided based on the available CPUs at the boot time. | 899 | * The capabilities were decided based on the available CPUs at the boot time. |
922 | * Any new CPU should match the system wide status of the capability. If the | 900 | * Any new CPU should match the system wide status of the capability. If the |
@@ -944,8 +922,11 @@ void verify_local_cpu_capabilities(void) | |||
944 | * If the new CPU misses an advertised feature, we cannot proceed | 922 | * If the new CPU misses an advertised feature, we cannot proceed |
945 | * further, park the cpu. | 923 | * further, park the cpu. |
946 | */ | 924 | */ |
947 | if (!feature_matches(__raw_read_system_reg(caps[i].sys_reg), &caps[i])) | 925 | if (!feature_matches(__raw_read_system_reg(caps[i].sys_reg), &caps[i])) { |
948 | fail_incapable_cpu("arm64_features", &caps[i]); | 926 | pr_crit("CPU%d: missing feature: %s\n", |
927 | smp_processor_id(), caps[i].desc); | ||
928 | cpu_die_early(); | ||
929 | } | ||
949 | if (caps[i].enable) | 930 | if (caps[i].enable) |
950 | caps[i].enable(NULL); | 931 | caps[i].enable(NULL); |
951 | } | 932 | } |
@@ -953,8 +934,11 @@ void verify_local_cpu_capabilities(void) | |||
953 | for (i = 0, caps = arm64_hwcaps; caps[i].matches; i++) { | 934 | for (i = 0, caps = arm64_hwcaps; caps[i].matches; i++) { |
954 | if (!cpus_have_hwcap(&caps[i])) | 935 | if (!cpus_have_hwcap(&caps[i])) |
955 | continue; | 936 | continue; |
956 | if (!feature_matches(__raw_read_system_reg(caps[i].sys_reg), &caps[i])) | 937 | if (!feature_matches(__raw_read_system_reg(caps[i].sys_reg), &caps[i])) { |
957 | fail_incapable_cpu("arm64_hwcaps", &caps[i]); | 938 | pr_crit("CPU%d: missing HWCAP: %s\n", |
939 | smp_processor_id(), caps[i].desc); | ||
940 | cpu_die_early(); | ||
941 | } | ||
958 | } | 942 | } |
959 | } | 943 | } |
960 | 944 | ||
diff --git a/arch/arm64/kernel/crash_dump.c b/arch/arm64/kernel/crash_dump.c new file mode 100644 index 000000000000..f46d57c31443 --- /dev/null +++ b/arch/arm64/kernel/crash_dump.c | |||
@@ -0,0 +1,71 @@ | |||
1 | /* | ||
2 | * Routines for doing kexec-based kdump | ||
3 | * | ||
4 | * Copyright (C) 2017 Linaro Limited | ||
5 | * Author: AKASHI Takahiro <takahiro.akashi@linaro.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/crash_dump.h> | ||
13 | #include <linux/errno.h> | ||
14 | #include <linux/io.h> | ||
15 | #include <linux/memblock.h> | ||
16 | #include <linux/uaccess.h> | ||
17 | #include <asm/memory.h> | ||
18 | |||
19 | /** | ||
20 | * copy_oldmem_page() - copy one page from old kernel memory | ||
21 | * @pfn: page frame number to be copied | ||
22 | * @buf: buffer where the copied page is placed | ||
23 | * @csize: number of bytes to copy | ||
24 | * @offset: offset in bytes into the page | ||
25 | * @userbuf: if set, @buf is in a user address space | ||
26 | * | ||
27 | * This function copies one page from old kernel memory into buffer pointed by | ||
28 | * @buf. If @buf is in userspace, set @userbuf to %1. Returns number of bytes | ||
29 | * copied or negative error in case of failure. | ||
30 | */ | ||
31 | ssize_t copy_oldmem_page(unsigned long pfn, char *buf, | ||
32 | size_t csize, unsigned long offset, | ||
33 | int userbuf) | ||
34 | { | ||
35 | void *vaddr; | ||
36 | |||
37 | if (!csize) | ||
38 | return 0; | ||
39 | |||
40 | vaddr = memremap(__pfn_to_phys(pfn), PAGE_SIZE, MEMREMAP_WB); | ||
41 | if (!vaddr) | ||
42 | return -ENOMEM; | ||
43 | |||
44 | if (userbuf) { | ||
45 | if (copy_to_user((char __user *)buf, vaddr + offset, csize)) { | ||
46 | memunmap(vaddr); | ||
47 | return -EFAULT; | ||
48 | } | ||
49 | } else { | ||
50 | memcpy(buf, vaddr + offset, csize); | ||
51 | } | ||
52 | |||
53 | memunmap(vaddr); | ||
54 | |||
55 | return csize; | ||
56 | } | ||
57 | |||
58 | /** | ||
59 | * elfcorehdr_read - read from ELF core header | ||
60 | * @buf: buffer where the data is placed | ||
61 | * @csize: number of bytes to read | ||
62 | * @ppos: address in the memory | ||
63 | * | ||
64 | * This function reads @count bytes from elf core header which exists | ||
65 | * on crash dump kernel's memory. | ||
66 | */ | ||
67 | ssize_t elfcorehdr_read(char *buf, size_t count, u64 *ppos) | ||
68 | { | ||
69 | memcpy(buf, phys_to_virt((phys_addr_t)*ppos), count); | ||
70 | return count; | ||
71 | } | ||
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 8cfd5ab37743..9c2e1564e9a7 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <asm/pgtable-hwdef.h> | 36 | #include <asm/pgtable-hwdef.h> |
37 | #include <asm/pgtable.h> | 37 | #include <asm/pgtable.h> |
38 | #include <asm/page.h> | 38 | #include <asm/page.h> |
39 | #include <asm/smp.h> | ||
39 | #include <asm/sysreg.h> | 40 | #include <asm/sysreg.h> |
40 | #include <asm/thread_info.h> | 41 | #include <asm/thread_info.h> |
41 | #include <asm/virt.h> | 42 | #include <asm/virt.h> |
@@ -643,7 +644,8 @@ __secondary_switched: | |||
643 | msr vbar_el1, x5 | 644 | msr vbar_el1, x5 |
644 | isb | 645 | isb |
645 | 646 | ||
646 | ldr_l x0, secondary_data // get secondary_data.stack | 647 | adr_l x0, secondary_data |
648 | ldr x0, [x0, #CPU_BOOT_STACK] // get secondary_data.stack | ||
647 | mov sp, x0 | 649 | mov sp, x0 |
648 | and x0, x0, #~(THREAD_SIZE - 1) | 650 | and x0, x0, #~(THREAD_SIZE - 1) |
649 | msr sp_el0, x0 // save thread_info | 651 | msr sp_el0, x0 // save thread_info |
@@ -652,6 +654,29 @@ __secondary_switched: | |||
652 | ENDPROC(__secondary_switched) | 654 | ENDPROC(__secondary_switched) |
653 | 655 | ||
654 | /* | 656 | /* |
657 | * The booting CPU updates the failed status @__early_cpu_boot_status, | ||
658 | * with MMU turned off. | ||
659 | * | ||
660 | * update_early_cpu_boot_status tmp, status | ||
661 | * - Corrupts tmp1, tmp2 | ||
662 | * - Writes 'status' to __early_cpu_boot_status and makes sure | ||
663 | * it is committed to memory. | ||
664 | */ | ||
665 | |||
666 | .macro update_early_cpu_boot_status status, tmp1, tmp2 | ||
667 | mov \tmp2, #\status | ||
668 | str_l \tmp2, __early_cpu_boot_status, \tmp1 | ||
669 | dmb sy | ||
670 | dc ivac, \tmp1 // Invalidate potentially stale cache line | ||
671 | .endm | ||
672 | |||
673 | .pushsection .data..cacheline_aligned | ||
674 | .align L1_CACHE_SHIFT | ||
675 | ENTRY(__early_cpu_boot_status) | ||
676 | .long 0 | ||
677 | .popsection | ||
678 | |||
679 | /* | ||
655 | * Enable the MMU. | 680 | * Enable the MMU. |
656 | * | 681 | * |
657 | * x0 = SCTLR_EL1 value for turning on the MMU. | 682 | * x0 = SCTLR_EL1 value for turning on the MMU. |
@@ -669,6 +694,7 @@ ENTRY(__enable_mmu) | |||
669 | ubfx x2, x1, #ID_AA64MMFR0_TGRAN_SHIFT, 4 | 694 | ubfx x2, x1, #ID_AA64MMFR0_TGRAN_SHIFT, 4 |
670 | cmp x2, #ID_AA64MMFR0_TGRAN_SUPPORTED | 695 | cmp x2, #ID_AA64MMFR0_TGRAN_SUPPORTED |
671 | b.ne __no_granule_support | 696 | b.ne __no_granule_support |
697 | update_early_cpu_boot_status 0, x1, x2 | ||
672 | msr ttbr0_el1, x25 // load TTBR0 | 698 | msr ttbr0_el1, x25 // load TTBR0 |
673 | msr ttbr1_el1, x26 // load TTBR1 | 699 | msr ttbr1_el1, x26 // load TTBR1 |
674 | isb | 700 | isb |
@@ -708,8 +734,12 @@ ENTRY(__enable_mmu) | |||
708 | ENDPROC(__enable_mmu) | 734 | ENDPROC(__enable_mmu) |
709 | 735 | ||
710 | __no_granule_support: | 736 | __no_granule_support: |
737 | /* Indicate that this CPU can't boot and is stuck in the kernel */ | ||
738 | update_early_cpu_boot_status CPU_STUCK_IN_KERNEL, x1, x2 | ||
739 | 1: | ||
711 | wfe | 740 | wfe |
712 | b __no_granule_support | 741 | wfi |
742 | b 1b | ||
713 | ENDPROC(__no_granule_support) | 743 | ENDPROC(__no_granule_support) |
714 | 744 | ||
715 | __primary_switch: | 745 | __primary_switch: |
diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c index 6dd18140ebb8..35a33d705536 100644 --- a/arch/arm64/kernel/hibernate.c +++ b/arch/arm64/kernel/hibernate.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <asm/barrier.h> | 27 | #include <asm/barrier.h> |
28 | #include <asm/cacheflush.h> | 28 | #include <asm/cacheflush.h> |
29 | #include <asm/irqflags.h> | 29 | #include <asm/irqflags.h> |
30 | #include <asm/kexec.h> | ||
30 | #include <asm/memory.h> | 31 | #include <asm/memory.h> |
31 | #include <asm/mmu_context.h> | 32 | #include <asm/mmu_context.h> |
32 | #include <asm/pgalloc.h> | 33 | #include <asm/pgalloc.h> |
@@ -100,7 +101,8 @@ int pfn_is_nosave(unsigned long pfn) | |||
100 | unsigned long nosave_begin_pfn = virt_to_pfn(&__nosave_begin); | 101 | unsigned long nosave_begin_pfn = virt_to_pfn(&__nosave_begin); |
101 | unsigned long nosave_end_pfn = virt_to_pfn(&__nosave_end - 1); | 102 | unsigned long nosave_end_pfn = virt_to_pfn(&__nosave_end - 1); |
102 | 103 | ||
103 | return (pfn >= nosave_begin_pfn) && (pfn <= nosave_end_pfn); | 104 | return ((pfn >= nosave_begin_pfn) && (pfn <= nosave_end_pfn)) || |
105 | crash_is_nosave(pfn); | ||
104 | } | 106 | } |
105 | 107 | ||
106 | void notrace save_processor_state(void) | 108 | void notrace save_processor_state(void) |
@@ -250,11 +252,17 @@ int swsusp_arch_suspend(void) | |||
250 | local_dbg_save(flags); | 252 | local_dbg_save(flags); |
251 | 253 | ||
252 | if (__cpu_suspend_enter(&state)) { | 254 | if (__cpu_suspend_enter(&state)) { |
255 | /* make the crash dump kernel image visible/saveable */ | ||
256 | crash_prepare_suspend(); | ||
257 | |||
253 | ret = swsusp_save(); | 258 | ret = swsusp_save(); |
254 | } else { | 259 | } else { |
255 | /* Clean kernel to PoC for secondary core startup */ | 260 | /* Clean kernel to PoC for secondary core startup */ |
256 | __flush_dcache_area(LMADDR(KERNEL_START), KERNEL_END - KERNEL_START); | 261 | __flush_dcache_area(LMADDR(KERNEL_START), KERNEL_END - KERNEL_START); |
257 | 262 | ||
263 | /* make the crash dump kernel image protected again */ | ||
264 | crash_post_resume(); | ||
265 | |||
258 | /* | 266 | /* |
259 | * Tell the hibernation core that we've just restored | 267 | * Tell the hibernation core that we've just restored |
260 | * the memory | 268 | * the memory |
diff --git a/arch/arm64/kernel/hyp-stub.S b/arch/arm64/kernel/hyp-stub.S index 8727f4490772..d3b5f75e652e 100644 --- a/arch/arm64/kernel/hyp-stub.S +++ b/arch/arm64/kernel/hyp-stub.S | |||
@@ -71,8 +71,16 @@ el1_sync: | |||
71 | msr vbar_el2, x1 | 71 | msr vbar_el2, x1 |
72 | b 9f | 72 | b 9f |
73 | 73 | ||
74 | 2: cmp x0, #HVC_SOFT_RESTART | ||
75 | b.ne 3f | ||
76 | mov x0, x2 | ||
77 | mov x2, x4 | ||
78 | mov x4, x1 | ||
79 | mov x1, x3 | ||
80 | br x4 // no return | ||
81 | |||
74 | /* Someone called kvm_call_hyp() against the hyp-stub... */ | 82 | /* Someone called kvm_call_hyp() against the hyp-stub... */ |
75 | 2: mov x0, #ARM_EXCEPTION_HYP_GONE | 83 | 3: mov x0, #ARM_EXCEPTION_HYP_GONE |
76 | 84 | ||
77 | 9: eret | 85 | 9: eret |
78 | ENDPROC(el1_sync) | 86 | ENDPROC(el1_sync) |
diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c new file mode 100644 index 000000000000..481f54a866c5 --- /dev/null +++ b/arch/arm64/kernel/machine_kexec.c | |||
@@ -0,0 +1,364 @@ | |||
1 | /* | ||
2 | * kexec for arm64 | ||
3 | * | ||
4 | * Copyright (C) Linaro. | ||
5 | * Copyright (C) Huawei Futurewei Technologies. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/interrupt.h> | ||
13 | #include <linux/irq.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/kexec.h> | ||
16 | #include <linux/page-flags.h> | ||
17 | #include <linux/smp.h> | ||
18 | |||
19 | #include <asm/cacheflush.h> | ||
20 | #include <asm/cpu_ops.h> | ||
21 | #include <asm/memory.h> | ||
22 | #include <asm/mmu.h> | ||
23 | #include <asm/mmu_context.h> | ||
24 | #include <asm/page.h> | ||
25 | |||
26 | #include "cpu-reset.h" | ||
27 | |||
28 | /* Global variables for the arm64_relocate_new_kernel routine. */ | ||
29 | extern const unsigned char arm64_relocate_new_kernel[]; | ||
30 | extern const unsigned long arm64_relocate_new_kernel_size; | ||
31 | |||
32 | /** | ||
33 | * kexec_image_info - For debugging output. | ||
34 | */ | ||
35 | #define kexec_image_info(_i) _kexec_image_info(__func__, __LINE__, _i) | ||
36 | static void _kexec_image_info(const char *func, int line, | ||
37 | const struct kimage *kimage) | ||
38 | { | ||
39 | unsigned long i; | ||
40 | |||
41 | pr_debug("%s:%d:\n", func, line); | ||
42 | pr_debug(" kexec kimage info:\n"); | ||
43 | pr_debug(" type: %d\n", kimage->type); | ||
44 | pr_debug(" start: %lx\n", kimage->start); | ||
45 | pr_debug(" head: %lx\n", kimage->head); | ||
46 | pr_debug(" nr_segments: %lu\n", kimage->nr_segments); | ||
47 | |||
48 | for (i = 0; i < kimage->nr_segments; i++) { | ||
49 | pr_debug(" segment[%lu]: %016lx - %016lx, 0x%lx bytes, %lu pages\n", | ||
50 | i, | ||
51 | kimage->segment[i].mem, | ||
52 | kimage->segment[i].mem + kimage->segment[i].memsz, | ||
53 | kimage->segment[i].memsz, | ||
54 | kimage->segment[i].memsz / PAGE_SIZE); | ||
55 | } | ||
56 | } | ||
57 | |||
58 | void machine_kexec_cleanup(struct kimage *kimage) | ||
59 | { | ||
60 | /* Empty routine needed to avoid build errors. */ | ||
61 | } | ||
62 | |||
63 | /** | ||
64 | * machine_kexec_prepare - Prepare for a kexec reboot. | ||
65 | * | ||
66 | * Called from the core kexec code when a kernel image is loaded. | ||
67 | * Forbid loading a kexec kernel if we have no way of hotplugging cpus or cpus | ||
68 | * are stuck in the kernel. This avoids a panic once we hit machine_kexec(). | ||
69 | */ | ||
70 | int machine_kexec_prepare(struct kimage *kimage) | ||
71 | { | ||
72 | kexec_image_info(kimage); | ||
73 | |||
74 | if (kimage->type != KEXEC_TYPE_CRASH && cpus_are_stuck_in_kernel()) { | ||
75 | pr_err("Can't kexec: CPUs are stuck in the kernel.\n"); | ||
76 | return -EBUSY; | ||
77 | } | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | /** | ||
83 | * kexec_list_flush - Helper to flush the kimage list and source pages to PoC. | ||
84 | */ | ||
85 | static void kexec_list_flush(struct kimage *kimage) | ||
86 | { | ||
87 | kimage_entry_t *entry; | ||
88 | |||
89 | for (entry = &kimage->head; ; entry++) { | ||
90 | unsigned int flag; | ||
91 | void *addr; | ||
92 | |||
93 | /* flush the list entries. */ | ||
94 | __flush_dcache_area(entry, sizeof(kimage_entry_t)); | ||
95 | |||
96 | flag = *entry & IND_FLAGS; | ||
97 | if (flag == IND_DONE) | ||
98 | break; | ||
99 | |||
100 | addr = phys_to_virt(*entry & PAGE_MASK); | ||
101 | |||
102 | switch (flag) { | ||
103 | case IND_INDIRECTION: | ||
104 | /* Set entry point just before the new list page. */ | ||
105 | entry = (kimage_entry_t *)addr - 1; | ||
106 | break; | ||
107 | case IND_SOURCE: | ||
108 | /* flush the source pages. */ | ||
109 | __flush_dcache_area(addr, PAGE_SIZE); | ||
110 | break; | ||
111 | case IND_DESTINATION: | ||
112 | break; | ||
113 | default: | ||
114 | BUG(); | ||
115 | } | ||
116 | } | ||
117 | } | ||
118 | |||
119 | /** | ||
120 | * kexec_segment_flush - Helper to flush the kimage segments to PoC. | ||
121 | */ | ||
122 | static void kexec_segment_flush(const struct kimage *kimage) | ||
123 | { | ||
124 | unsigned long i; | ||
125 | |||
126 | pr_debug("%s:\n", __func__); | ||
127 | |||
128 | for (i = 0; i < kimage->nr_segments; i++) { | ||
129 | pr_debug(" segment[%lu]: %016lx - %016lx, 0x%lx bytes, %lu pages\n", | ||
130 | i, | ||
131 | kimage->segment[i].mem, | ||
132 | kimage->segment[i].mem + kimage->segment[i].memsz, | ||
133 | kimage->segment[i].memsz, | ||
134 | kimage->segment[i].memsz / PAGE_SIZE); | ||
135 | |||
136 | __flush_dcache_area(phys_to_virt(kimage->segment[i].mem), | ||
137 | kimage->segment[i].memsz); | ||
138 | } | ||
139 | } | ||
140 | |||
141 | /** | ||
142 | * machine_kexec - Do the kexec reboot. | ||
143 | * | ||
144 | * Called from the core kexec code for a sys_reboot with LINUX_REBOOT_CMD_KEXEC. | ||
145 | */ | ||
146 | void machine_kexec(struct kimage *kimage) | ||
147 | { | ||
148 | phys_addr_t reboot_code_buffer_phys; | ||
149 | void *reboot_code_buffer; | ||
150 | bool in_kexec_crash = (kimage == kexec_crash_image); | ||
151 | bool stuck_cpus = cpus_are_stuck_in_kernel(); | ||
152 | |||
153 | /* | ||
154 | * New cpus may have become stuck_in_kernel after we loaded the image. | ||
155 | */ | ||
156 | BUG_ON(!in_kexec_crash && (stuck_cpus || (num_online_cpus() > 1))); | ||
157 | WARN(in_kexec_crash && (stuck_cpus || smp_crash_stop_failed()), | ||
158 | "Some CPUs may be stale, kdump will be unreliable.\n"); | ||
159 | |||
160 | reboot_code_buffer_phys = page_to_phys(kimage->control_code_page); | ||
161 | reboot_code_buffer = phys_to_virt(reboot_code_buffer_phys); | ||
162 | |||
163 | kexec_image_info(kimage); | ||
164 | |||
165 | pr_debug("%s:%d: control_code_page: %p\n", __func__, __LINE__, | ||
166 | kimage->control_code_page); | ||
167 | pr_debug("%s:%d: reboot_code_buffer_phys: %pa\n", __func__, __LINE__, | ||
168 | &reboot_code_buffer_phys); | ||
169 | pr_debug("%s:%d: reboot_code_buffer: %p\n", __func__, __LINE__, | ||
170 | reboot_code_buffer); | ||
171 | pr_debug("%s:%d: relocate_new_kernel: %p\n", __func__, __LINE__, | ||
172 | arm64_relocate_new_kernel); | ||
173 | pr_debug("%s:%d: relocate_new_kernel_size: 0x%lx(%lu) bytes\n", | ||
174 | __func__, __LINE__, arm64_relocate_new_kernel_size, | ||
175 | arm64_relocate_new_kernel_size); | ||
176 | |||
177 | /* | ||
178 | * Copy arm64_relocate_new_kernel to the reboot_code_buffer for use | ||
179 | * after the kernel is shut down. | ||
180 | */ | ||
181 | memcpy(reboot_code_buffer, arm64_relocate_new_kernel, | ||
182 | arm64_relocate_new_kernel_size); | ||
183 | |||
184 | /* Flush the reboot_code_buffer in preparation for its execution. */ | ||
185 | __flush_dcache_area(reboot_code_buffer, arm64_relocate_new_kernel_size); | ||
186 | flush_icache_range((uintptr_t)reboot_code_buffer, | ||
187 | arm64_relocate_new_kernel_size); | ||
188 | |||
189 | /* Flush the kimage list and its buffers. */ | ||
190 | kexec_list_flush(kimage); | ||
191 | |||
192 | /* Flush the new image if already in place. */ | ||
193 | if ((kimage != kexec_crash_image) && (kimage->head & IND_DONE)) | ||
194 | kexec_segment_flush(kimage); | ||
195 | |||
196 | pr_info("Bye!\n"); | ||
197 | |||
198 | /* Disable all DAIF exceptions. */ | ||
199 | asm volatile ("msr daifset, #0xf" : : : "memory"); | ||
200 | |||
201 | /* | ||
202 | * cpu_soft_restart will shutdown the MMU, disable data caches, then | ||
203 | * transfer control to the reboot_code_buffer which contains a copy of | ||
204 | * the arm64_relocate_new_kernel routine. arm64_relocate_new_kernel | ||
205 | * uses physical addressing to relocate the new image to its final | ||
206 | * position and transfers control to the image entry point when the | ||
207 | * relocation is complete. | ||
208 | */ | ||
209 | |||
210 | cpu_soft_restart(kimage != kexec_crash_image, | ||
211 | reboot_code_buffer_phys, kimage->head, kimage->start, 0); | ||
212 | |||
213 | BUG(); /* Should never get here. */ | ||
214 | } | ||
215 | |||
216 | static void machine_kexec_mask_interrupts(void) | ||
217 | { | ||
218 | unsigned int i; | ||
219 | struct irq_desc *desc; | ||
220 | |||
221 | for_each_irq_desc(i, desc) { | ||
222 | struct irq_chip *chip; | ||
223 | int ret; | ||
224 | |||
225 | chip = irq_desc_get_chip(desc); | ||
226 | if (!chip) | ||
227 | continue; | ||
228 | |||
229 | /* | ||
230 | * First try to remove the active state. If this | ||
231 | * fails, try to EOI the interrupt. | ||
232 | */ | ||
233 | ret = irq_set_irqchip_state(i, IRQCHIP_STATE_ACTIVE, false); | ||
234 | |||
235 | if (ret && irqd_irq_inprogress(&desc->irq_data) && | ||
236 | chip->irq_eoi) | ||
237 | chip->irq_eoi(&desc->irq_data); | ||
238 | |||
239 | if (chip->irq_mask) | ||
240 | chip->irq_mask(&desc->irq_data); | ||
241 | |||
242 | if (chip->irq_disable && !irqd_irq_disabled(&desc->irq_data)) | ||
243 | chip->irq_disable(&desc->irq_data); | ||
244 | } | ||
245 | } | ||
246 | |||
247 | /** | ||
248 | * machine_crash_shutdown - shutdown non-crashing cpus and save registers | ||
249 | */ | ||
250 | void machine_crash_shutdown(struct pt_regs *regs) | ||
251 | { | ||
252 | local_irq_disable(); | ||
253 | |||
254 | /* shutdown non-crashing cpus */ | ||
255 | smp_send_crash_stop(); | ||
256 | |||
257 | /* for crashing cpu */ | ||
258 | crash_save_cpu(regs, smp_processor_id()); | ||
259 | machine_kexec_mask_interrupts(); | ||
260 | |||
261 | pr_info("Starting crashdump kernel...\n"); | ||
262 | } | ||
263 | |||
264 | void arch_kexec_protect_crashkres(void) | ||
265 | { | ||
266 | int i; | ||
267 | |||
268 | kexec_segment_flush(kexec_crash_image); | ||
269 | |||
270 | for (i = 0; i < kexec_crash_image->nr_segments; i++) | ||
271 | set_memory_valid( | ||
272 | __phys_to_virt(kexec_crash_image->segment[i].mem), | ||
273 | kexec_crash_image->segment[i].memsz >> PAGE_SHIFT, 0); | ||
274 | } | ||
275 | |||
276 | void arch_kexec_unprotect_crashkres(void) | ||
277 | { | ||
278 | int i; | ||
279 | |||
280 | for (i = 0; i < kexec_crash_image->nr_segments; i++) | ||
281 | set_memory_valid( | ||
282 | __phys_to_virt(kexec_crash_image->segment[i].mem), | ||
283 | kexec_crash_image->segment[i].memsz >> PAGE_SHIFT, 1); | ||
284 | } | ||
285 | |||
286 | #ifdef CONFIG_HIBERNATION | ||
287 | /* | ||
288 | * To preserve the crash dump kernel image, the relevant memory segments | ||
289 | * should be mapped again around the hibernation. | ||
290 | */ | ||
291 | void crash_prepare_suspend(void) | ||
292 | { | ||
293 | if (kexec_crash_image) | ||
294 | arch_kexec_unprotect_crashkres(); | ||
295 | } | ||
296 | |||
297 | void crash_post_resume(void) | ||
298 | { | ||
299 | if (kexec_crash_image) | ||
300 | arch_kexec_protect_crashkres(); | ||
301 | } | ||
302 | |||
303 | /* | ||
304 | * crash_is_nosave | ||
305 | * | ||
306 | * Return true only if a page is part of reserved memory for crash dump kernel, | ||
307 | * but does not hold any data of loaded kernel image. | ||
308 | * | ||
309 | * Note that all the pages in crash dump kernel memory have been initially | ||
310 | * marked as Reserved in kexec_reserve_crashkres_pages(). | ||
311 | * | ||
312 | * In hibernation, the pages which are Reserved and yet "nosave" are excluded | ||
313 | * from the hibernation iamge. crash_is_nosave() does thich check for crash | ||
314 | * dump kernel and will reduce the total size of hibernation image. | ||
315 | */ | ||
316 | |||
317 | bool crash_is_nosave(unsigned long pfn) | ||
318 | { | ||
319 | int i; | ||
320 | phys_addr_t addr; | ||
321 | |||
322 | if (!crashk_res.end) | ||
323 | return false; | ||
324 | |||
325 | /* in reserved memory? */ | ||
326 | addr = __pfn_to_phys(pfn); | ||
327 | if ((addr < crashk_res.start) || (crashk_res.end < addr)) | ||
328 | return false; | ||
329 | |||
330 | if (!kexec_crash_image) | ||
331 | return true; | ||
332 | |||
333 | /* not part of loaded kernel image? */ | ||
334 | for (i = 0; i < kexec_crash_image->nr_segments; i++) | ||
335 | if (addr >= kexec_crash_image->segment[i].mem && | ||
336 | addr < (kexec_crash_image->segment[i].mem + | ||
337 | kexec_crash_image->segment[i].memsz)) | ||
338 | return false; | ||
339 | |||
340 | return true; | ||
341 | } | ||
342 | |||
343 | void crash_free_reserved_phys_range(unsigned long begin, unsigned long end) | ||
344 | { | ||
345 | unsigned long addr; | ||
346 | struct page *page; | ||
347 | |||
348 | for (addr = begin; addr < end; addr += PAGE_SIZE) { | ||
349 | page = phys_to_page(addr); | ||
350 | ClearPageReserved(page); | ||
351 | free_reserved_page(page); | ||
352 | } | ||
353 | } | ||
354 | #endif /* CONFIG_HIBERNATION */ | ||
355 | |||
356 | void arch_crash_save_vmcoreinfo(void) | ||
357 | { | ||
358 | VMCOREINFO_NUMBER(VA_BITS); | ||
359 | /* Please note VMCOREINFO_NUMBER() uses "%d", not "%x" */ | ||
360 | vmcoreinfo_append_str("NUMBER(kimage_voffset)=0x%llx\n", | ||
361 | kimage_voffset); | ||
362 | vmcoreinfo_append_str("NUMBER(PHYS_OFFSET)=0x%llx\n", | ||
363 | PHYS_OFFSET); | ||
364 | } | ||
diff --git a/arch/arm64/kernel/relocate_kernel.S b/arch/arm64/kernel/relocate_kernel.S new file mode 100644 index 000000000000..51b73cdde287 --- /dev/null +++ b/arch/arm64/kernel/relocate_kernel.S | |||
@@ -0,0 +1,130 @@ | |||
1 | /* | ||
2 | * kexec for arm64 | ||
3 | * | ||
4 | * Copyright (C) Linaro. | ||
5 | * Copyright (C) Huawei Futurewei Technologies. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kexec.h> | ||
13 | #include <linux/linkage.h> | ||
14 | |||
15 | #include <asm/assembler.h> | ||
16 | #include <asm/kexec.h> | ||
17 | #include <asm/page.h> | ||
18 | #include <asm/sysreg.h> | ||
19 | |||
20 | /* | ||
21 | * arm64_relocate_new_kernel - Put a 2nd stage image in place and boot it. | ||
22 | * | ||
23 | * The memory that the old kernel occupies may be overwritten when coping the | ||
24 | * new image to its final location. To assure that the | ||
25 | * arm64_relocate_new_kernel routine which does that copy is not overwritten, | ||
26 | * all code and data needed by arm64_relocate_new_kernel must be between the | ||
27 | * symbols arm64_relocate_new_kernel and arm64_relocate_new_kernel_end. The | ||
28 | * machine_kexec() routine will copy arm64_relocate_new_kernel to the kexec | ||
29 | * control_code_page, a special page which has been set up to be preserved | ||
30 | * during the copy operation. | ||
31 | */ | ||
32 | ENTRY(arm64_relocate_new_kernel) | ||
33 | |||
34 | /* Setup the list loop variables. */ | ||
35 | mov x17, x1 /* x17 = kimage_start */ | ||
36 | mov x16, x0 /* x16 = kimage_head */ | ||
37 | dcache_line_size x15, x0 /* x15 = dcache line size */ | ||
38 | mov x14, xzr /* x14 = entry ptr */ | ||
39 | mov x13, xzr /* x13 = copy dest */ | ||
40 | |||
41 | /* Clear the sctlr_el2 flags. */ | ||
42 | mrs x0, CurrentEL | ||
43 | cmp x0, #CurrentEL_EL2 | ||
44 | b.ne 1f | ||
45 | mrs x0, sctlr_el2 | ||
46 | ldr x1, =SCTLR_ELx_FLAGS | ||
47 | bic x0, x0, x1 | ||
48 | msr sctlr_el2, x0 | ||
49 | isb | ||
50 | 1: | ||
51 | |||
52 | /* Check if the new image needs relocation. */ | ||
53 | tbnz x16, IND_DONE_BIT, .Ldone | ||
54 | |||
55 | .Lloop: | ||
56 | and x12, x16, PAGE_MASK /* x12 = addr */ | ||
57 | |||
58 | /* Test the entry flags. */ | ||
59 | .Ltest_source: | ||
60 | tbz x16, IND_SOURCE_BIT, .Ltest_indirection | ||
61 | |||
62 | /* Invalidate dest page to PoC. */ | ||
63 | mov x0, x13 | ||
64 | add x20, x0, #PAGE_SIZE | ||
65 | sub x1, x15, #1 | ||
66 | bic x0, x0, x1 | ||
67 | 2: dc ivac, x0 | ||
68 | add x0, x0, x15 | ||
69 | cmp x0, x20 | ||
70 | b.lo 2b | ||
71 | dsb sy | ||
72 | |||
73 | mov x20, x13 | ||
74 | mov x21, x12 | ||
75 | copy_page x20, x21, x0, x1, x2, x3, x4, x5, x6, x7 | ||
76 | |||
77 | /* dest += PAGE_SIZE */ | ||
78 | add x13, x13, PAGE_SIZE | ||
79 | b .Lnext | ||
80 | |||
81 | .Ltest_indirection: | ||
82 | tbz x16, IND_INDIRECTION_BIT, .Ltest_destination | ||
83 | |||
84 | /* ptr = addr */ | ||
85 | mov x14, x12 | ||
86 | b .Lnext | ||
87 | |||
88 | .Ltest_destination: | ||
89 | tbz x16, IND_DESTINATION_BIT, .Lnext | ||
90 | |||
91 | /* dest = addr */ | ||
92 | mov x13, x12 | ||
93 | |||
94 | .Lnext: | ||
95 | /* entry = *ptr++ */ | ||
96 | ldr x16, [x14], #8 | ||
97 | |||
98 | /* while (!(entry & DONE)) */ | ||
99 | tbz x16, IND_DONE_BIT, .Lloop | ||
100 | |||
101 | .Ldone: | ||
102 | /* wait for writes from copy_page to finish */ | ||
103 | dsb nsh | ||
104 | ic iallu | ||
105 | dsb nsh | ||
106 | isb | ||
107 | |||
108 | /* Start new image. */ | ||
109 | mov x0, xzr | ||
110 | mov x1, xzr | ||
111 | mov x2, xzr | ||
112 | mov x3, xzr | ||
113 | br x17 | ||
114 | |||
115 | ENDPROC(arm64_relocate_new_kernel) | ||
116 | |||
117 | .ltorg | ||
118 | |||
119 | .align 3 /* To keep the 64-bit values below naturally aligned. */ | ||
120 | |||
121 | .Lcopy_end: | ||
122 | .org KEXEC_CONTROL_PAGE_SIZE | ||
123 | |||
124 | /* | ||
125 | * arm64_relocate_new_kernel_size - Number of bytes to copy to the | ||
126 | * control_code_page. | ||
127 | */ | ||
128 | .globl arm64_relocate_new_kernel_size | ||
129 | arm64_relocate_new_kernel_size: | ||
130 | .quad .Lcopy_end - arm64_relocate_new_kernel | ||
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 0153c0d8ddb1..19749870c757 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <linux/screen_info.h> | 31 | #include <linux/screen_info.h> |
32 | #include <linux/init.h> | 32 | #include <linux/init.h> |
33 | #include <linux/kexec.h> | 33 | #include <linux/kexec.h> |
34 | #include <linux/crash_dump.h> | ||
35 | #include <linux/root_dev.h> | 34 | #include <linux/root_dev.h> |
36 | #include <linux/cpu.h> | 35 | #include <linux/cpu.h> |
37 | #include <linux/interrupt.h> | 36 | #include <linux/interrupt.h> |
@@ -220,6 +219,12 @@ static void __init request_standard_resources(void) | |||
220 | if (kernel_data.start >= res->start && | 219 | if (kernel_data.start >= res->start && |
221 | kernel_data.end <= res->end) | 220 | kernel_data.end <= res->end) |
222 | request_resource(res, &kernel_data); | 221 | request_resource(res, &kernel_data); |
222 | #ifdef CONFIG_KEXEC_CORE | ||
223 | /* Userspace will find "Crash kernel" region in /proc/iomem. */ | ||
224 | if (crashk_res.end && crashk_res.start >= res->start && | ||
225 | crashk_res.end <= res->end) | ||
226 | request_resource(res, &crashk_res); | ||
227 | #endif | ||
223 | } | 228 | } |
224 | } | 229 | } |
225 | 230 | ||
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index a84623d91410..a1d06fc42048 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/completion.h> | 37 | #include <linux/completion.h> |
38 | #include <linux/of.h> | 38 | #include <linux/of.h> |
39 | #include <linux/irq_work.h> | 39 | #include <linux/irq_work.h> |
40 | #include <linux/kexec.h> | ||
40 | 41 | ||
41 | #include <asm/alternative.h> | 42 | #include <asm/alternative.h> |
42 | #include <asm/atomic.h> | 43 | #include <asm/atomic.h> |
@@ -63,16 +64,29 @@ | |||
63 | * where to place its SVC stack | 64 | * where to place its SVC stack |
64 | */ | 65 | */ |
65 | struct secondary_data secondary_data; | 66 | struct secondary_data secondary_data; |
67 | /* Number of CPUs which aren't online, but looping in kernel text. */ | ||
68 | int cpus_stuck_in_kernel; | ||
66 | 69 | ||
67 | enum ipi_msg_type { | 70 | enum ipi_msg_type { |
68 | IPI_RESCHEDULE, | 71 | IPI_RESCHEDULE, |
69 | IPI_CALL_FUNC, | 72 | IPI_CALL_FUNC, |
70 | IPI_CPU_STOP, | 73 | IPI_CPU_STOP, |
74 | IPI_CPU_CRASH_STOP, | ||
71 | IPI_TIMER, | 75 | IPI_TIMER, |
72 | IPI_IRQ_WORK, | 76 | IPI_IRQ_WORK, |
73 | IPI_WAKEUP | 77 | IPI_WAKEUP |
74 | }; | 78 | }; |
75 | 79 | ||
80 | #ifdef CONFIG_HOTPLUG_CPU | ||
81 | static int op_cpu_kill(unsigned int cpu); | ||
82 | #else | ||
83 | static inline int op_cpu_kill(unsigned int cpu) | ||
84 | { | ||
85 | return -ENOSYS; | ||
86 | } | ||
87 | #endif | ||
88 | |||
89 | |||
76 | /* | 90 | /* |
77 | * Boot a secondary CPU, and assign it the specified idle task. | 91 | * Boot a secondary CPU, and assign it the specified idle task. |
78 | * This also gives us the initial stack to use for this CPU. | 92 | * This also gives us the initial stack to use for this CPU. |
@@ -90,12 +104,14 @@ static DECLARE_COMPLETION(cpu_running); | |||
90 | int __cpu_up(unsigned int cpu, struct task_struct *idle) | 104 | int __cpu_up(unsigned int cpu, struct task_struct *idle) |
91 | { | 105 | { |
92 | int ret; | 106 | int ret; |
107 | long status; | ||
93 | 108 | ||
94 | /* | 109 | /* |
95 | * We need to tell the secondary core where to find its stack and the | 110 | * We need to tell the secondary core where to find its stack and the |
96 | * page tables. | 111 | * page tables. |
97 | */ | 112 | */ |
98 | secondary_data.stack = task_stack_page(idle) + THREAD_START_SP; | 113 | secondary_data.stack = task_stack_page(idle) + THREAD_START_SP; |
114 | update_cpu_boot_status(CPU_MMU_OFF); | ||
99 | __flush_dcache_area(&secondary_data, sizeof(secondary_data)); | 115 | __flush_dcache_area(&secondary_data, sizeof(secondary_data)); |
100 | 116 | ||
101 | /* | 117 | /* |
@@ -119,6 +135,32 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle) | |||
119 | } | 135 | } |
120 | 136 | ||
121 | secondary_data.stack = NULL; | 137 | secondary_data.stack = NULL; |
138 | status = READ_ONCE(secondary_data.status); | ||
139 | if (ret && status) { | ||
140 | |||
141 | if (status == CPU_MMU_OFF) | ||
142 | status = READ_ONCE(__early_cpu_boot_status); | ||
143 | |||
144 | switch (status) { | ||
145 | default: | ||
146 | pr_err("CPU%u: failed in unknown state : 0x%lx\n", | ||
147 | cpu, status); | ||
148 | break; | ||
149 | case CPU_KILL_ME: | ||
150 | if (!op_cpu_kill(cpu)) { | ||
151 | pr_crit("CPU%u: died during early boot\n", cpu); | ||
152 | break; | ||
153 | } | ||
154 | /* Fall through */ | ||
155 | pr_crit("CPU%u: may not have shut down cleanly\n", cpu); | ||
156 | case CPU_STUCK_IN_KERNEL: | ||
157 | pr_crit("CPU%u: is stuck in kernel\n", cpu); | ||
158 | cpus_stuck_in_kernel++; | ||
159 | break; | ||
160 | case CPU_PANIC_KERNEL: | ||
161 | panic("CPU%u detected unsupported configuration\n", cpu); | ||
162 | } | ||
163 | } | ||
122 | 164 | ||
123 | return ret; | 165 | return ret; |
124 | } | 166 | } |
@@ -184,6 +226,9 @@ asmlinkage void secondary_start_kernel(void) | |||
184 | */ | 226 | */ |
185 | pr_info("CPU%u: Booted secondary processor [%08x]\n", | 227 | pr_info("CPU%u: Booted secondary processor [%08x]\n", |
186 | cpu, read_cpuid_id()); | 228 | cpu, read_cpuid_id()); |
229 | update_cpu_boot_status(CPU_BOOT_SUCCESS); | ||
230 | /* Make sure the status update is visible before we complete */ | ||
231 | smp_wmb(); | ||
187 | set_cpu_online(cpu, true); | 232 | set_cpu_online(cpu, true); |
188 | complete(&cpu_running); | 233 | complete(&cpu_running); |
189 | 234 | ||
@@ -311,6 +356,30 @@ void cpu_die(void) | |||
311 | } | 356 | } |
312 | #endif | 357 | #endif |
313 | 358 | ||
359 | /* | ||
360 | * Kill the calling secondary CPU, early in bringup before it is turned | ||
361 | * online. | ||
362 | */ | ||
363 | void cpu_die_early(void) | ||
364 | { | ||
365 | int cpu = smp_processor_id(); | ||
366 | |||
367 | pr_crit("CPU%d: will not boot\n", cpu); | ||
368 | |||
369 | /* Mark this CPU absent */ | ||
370 | set_cpu_present(cpu, 0); | ||
371 | |||
372 | #ifdef CONFIG_HOTPLUG_CPU | ||
373 | update_cpu_boot_status(CPU_KILL_ME); | ||
374 | /* Check if we can park ourselves */ | ||
375 | if (cpu_ops[cpu] && cpu_ops[cpu]->cpu_die) | ||
376 | cpu_ops[cpu]->cpu_die(cpu); | ||
377 | #endif | ||
378 | update_cpu_boot_status(CPU_STUCK_IN_KERNEL); | ||
379 | |||
380 | cpu_park_loop(); | ||
381 | } | ||
382 | |||
314 | static void __init hyp_mode_check(void) | 383 | static void __init hyp_mode_check(void) |
315 | { | 384 | { |
316 | if (is_hyp_mode_available()) | 385 | if (is_hyp_mode_available()) |
@@ -634,6 +703,7 @@ static const char *ipi_types[NR_IPI] __tracepoint_string = { | |||
634 | S(IPI_RESCHEDULE, "Rescheduling interrupts"), | 703 | S(IPI_RESCHEDULE, "Rescheduling interrupts"), |
635 | S(IPI_CALL_FUNC, "Function call interrupts"), | 704 | S(IPI_CALL_FUNC, "Function call interrupts"), |
636 | S(IPI_CPU_STOP, "CPU stop interrupts"), | 705 | S(IPI_CPU_STOP, "CPU stop interrupts"), |
706 | S(IPI_CPU_CRASH_STOP, "CPU stop (for crash dump) interrupts"), | ||
637 | S(IPI_TIMER, "Timer broadcast interrupts"), | 707 | S(IPI_TIMER, "Timer broadcast interrupts"), |
638 | S(IPI_IRQ_WORK, "IRQ work interrupts"), | 708 | S(IPI_IRQ_WORK, "IRQ work interrupts"), |
639 | S(IPI_WAKEUP, "CPU wake-up interrupts"), | 709 | S(IPI_WAKEUP, "CPU wake-up interrupts"), |
@@ -718,6 +788,29 @@ static void ipi_cpu_stop(unsigned int cpu) | |||
718 | cpu_relax(); | 788 | cpu_relax(); |
719 | } | 789 | } |
720 | 790 | ||
791 | #ifdef CONFIG_KEXEC_CORE | ||
792 | static atomic_t waiting_for_crash_ipi = ATOMIC_INIT(0); | ||
793 | #endif | ||
794 | |||
795 | static void ipi_cpu_crash_stop(unsigned int cpu, struct pt_regs *regs) | ||
796 | { | ||
797 | #ifdef CONFIG_KEXEC_CORE | ||
798 | crash_save_cpu(regs, cpu); | ||
799 | |||
800 | atomic_dec(&waiting_for_crash_ipi); | ||
801 | |||
802 | local_irq_disable(); | ||
803 | |||
804 | #ifdef CONFIG_HOTPLUG_CPU | ||
805 | if (cpu_ops[cpu]->cpu_die) | ||
806 | cpu_ops[cpu]->cpu_die(cpu); | ||
807 | #endif | ||
808 | |||
809 | /* just in case */ | ||
810 | cpu_park_loop(); | ||
811 | #endif | ||
812 | } | ||
813 | |||
721 | /* | 814 | /* |
722 | * Main handler for inter-processor interrupts | 815 | * Main handler for inter-processor interrupts |
723 | */ | 816 | */ |
@@ -748,6 +841,15 @@ void handle_IPI(int ipinr, struct pt_regs *regs) | |||
748 | irq_exit(); | 841 | irq_exit(); |
749 | break; | 842 | break; |
750 | 843 | ||
844 | case IPI_CPU_CRASH_STOP: | ||
845 | if (IS_ENABLED(CONFIG_KEXEC_CORE)) { | ||
846 | irq_enter(); | ||
847 | ipi_cpu_crash_stop(cpu, regs); | ||
848 | |||
849 | unreachable(); | ||
850 | } | ||
851 | break; | ||
852 | |||
751 | #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST | 853 | #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST |
752 | case IPI_TIMER: | 854 | case IPI_TIMER: |
753 | irq_enter(); | 855 | irq_enter(); |
@@ -816,6 +918,39 @@ void smp_send_stop(void) | |||
816 | pr_warning("SMP: failed to stop secondary CPUs\n"); | 918 | pr_warning("SMP: failed to stop secondary CPUs\n"); |
817 | } | 919 | } |
818 | 920 | ||
921 | #ifdef CONFIG_KEXEC_CORE | ||
922 | void smp_send_crash_stop(void) | ||
923 | { | ||
924 | cpumask_t mask; | ||
925 | unsigned long timeout; | ||
926 | |||
927 | if (num_online_cpus() == 1) | ||
928 | return; | ||
929 | |||
930 | cpumask_copy(&mask, cpu_online_mask); | ||
931 | cpumask_clear_cpu(smp_processor_id(), &mask); | ||
932 | |||
933 | atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1); | ||
934 | |||
935 | pr_crit("SMP: stopping secondary CPUs\n"); | ||
936 | smp_cross_call(&mask, IPI_CPU_CRASH_STOP); | ||
937 | |||
938 | /* Wait up to one second for other CPUs to stop */ | ||
939 | timeout = USEC_PER_SEC; | ||
940 | while ((atomic_read(&waiting_for_crash_ipi) > 0) && timeout--) | ||
941 | udelay(1); | ||
942 | |||
943 | if (atomic_read(&waiting_for_crash_ipi) > 0) | ||
944 | pr_warning("SMP: failed to stop secondary CPUs %*pbl\n", | ||
945 | cpumask_pr_args(&mask)); | ||
946 | } | ||
947 | |||
948 | bool smp_crash_stop_failed(void) | ||
949 | { | ||
950 | return (atomic_read(&waiting_for_crash_ipi) > 0); | ||
951 | } | ||
952 | #endif | ||
953 | |||
819 | /* | 954 | /* |
820 | * not supported here | 955 | * not supported here |
821 | */ | 956 | */ |
@@ -823,3 +958,21 @@ int setup_profiling_timer(unsigned int multiplier) | |||
823 | { | 958 | { |
824 | return -EINVAL; | 959 | return -EINVAL; |
825 | } | 960 | } |
961 | |||
962 | static bool have_cpu_die(void) | ||
963 | { | ||
964 | #ifdef CONFIG_HOTPLUG_CPU | ||
965 | int any_cpu = raw_smp_processor_id(); | ||
966 | |||
967 | if (cpu_ops[any_cpu]->cpu_die) | ||
968 | return true; | ||
969 | #endif | ||
970 | return false; | ||
971 | } | ||
972 | |||
973 | bool cpus_are_stuck_in_kernel(void) | ||
974 | { | ||
975 | bool smp_spin_tables = (num_possible_cpus() > 1 && !have_cpu_die()); | ||
976 | |||
977 | return !!cpus_stuck_in_kernel || smp_spin_tables; | ||
978 | } | ||
diff --git a/arch/arm64/kvm/hyp/Makefile b/arch/arm64/kvm/hyp/Makefile index 826032bc3945..acde4782621a 100644 --- a/arch/arm64/kvm/hyp/Makefile +++ b/arch/arm64/kvm/hyp/Makefile | |||
@@ -12,3 +12,7 @@ obj-$(CONFIG_KVM_ARM_HOST) += switch.o | |||
12 | obj-$(CONFIG_KVM_ARM_HOST) += fpsimd.o | 12 | obj-$(CONFIG_KVM_ARM_HOST) += fpsimd.o |
13 | obj-$(CONFIG_KVM_ARM_HOST) += tlb.o | 13 | obj-$(CONFIG_KVM_ARM_HOST) += tlb.o |
14 | obj-$(CONFIG_KVM_ARM_HOST) += hyp-entry.o | 14 | obj-$(CONFIG_KVM_ARM_HOST) += hyp-entry.o |
15 | |||
16 | GCOV_PROFILE := n | ||
17 | KASAN_SANITIZE := n | ||
18 | UBSAN_SANITIZE := n | ||
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index 678878077996..74ac8a90ba3f 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c | |||
@@ -29,11 +29,14 @@ | |||
29 | #include <linux/gfp.h> | 29 | #include <linux/gfp.h> |
30 | #include <linux/memblock.h> | 30 | #include <linux/memblock.h> |
31 | #include <linux/sort.h> | 31 | #include <linux/sort.h> |
32 | #include <linux/of.h> | ||
32 | #include <linux/of_fdt.h> | 33 | #include <linux/of_fdt.h> |
33 | #include <linux/dma-mapping.h> | 34 | #include <linux/dma-mapping.h> |
34 | #include <linux/dma-contiguous.h> | 35 | #include <linux/dma-contiguous.h> |
35 | #include <linux/efi.h> | 36 | #include <linux/efi.h> |
36 | #include <linux/swiotlb.h> | 37 | #include <linux/swiotlb.h> |
38 | #include <linux/kexec.h> | ||
39 | #include <linux/crash_dump.h> | ||
37 | 40 | ||
38 | #include <asm/boot.h> | 41 | #include <asm/boot.h> |
39 | #include <asm/fixmap.h> | 42 | #include <asm/fixmap.h> |
@@ -75,6 +78,142 @@ static int __init early_initrd(char *p) | |||
75 | early_param("initrd", early_initrd); | 78 | early_param("initrd", early_initrd); |
76 | #endif | 79 | #endif |
77 | 80 | ||
81 | #ifdef CONFIG_KEXEC_CORE | ||
82 | /* | ||
83 | * reserve_crashkernel() - reserves memory for crash kernel | ||
84 | * | ||
85 | * This function reserves memory area given in "crashkernel=" kernel command | ||
86 | * line parameter. The memory reserved is used by dump capture kernel when | ||
87 | * primary kernel is crashing. | ||
88 | */ | ||
89 | static void __init reserve_crashkernel(void) | ||
90 | { | ||
91 | unsigned long long crash_base, crash_size; | ||
92 | int ret; | ||
93 | |||
94 | ret = parse_crashkernel(boot_command_line, memblock_phys_mem_size(), | ||
95 | &crash_size, &crash_base); | ||
96 | /* no crashkernel= or invalid value specified */ | ||
97 | if (ret || !crash_size) | ||
98 | return; | ||
99 | |||
100 | crash_size = PAGE_ALIGN(crash_size); | ||
101 | |||
102 | if (crash_base == 0) { | ||
103 | /* Current arm64 boot protocol requires 2MB alignment */ | ||
104 | crash_base = memblock_find_in_range(0, ARCH_LOW_ADDRESS_LIMIT, | ||
105 | crash_size, SZ_2M); | ||
106 | if (crash_base == 0) { | ||
107 | pr_warn("cannot allocate crashkernel (size:0x%llx)\n", | ||
108 | crash_size); | ||
109 | return; | ||
110 | } | ||
111 | } else { | ||
112 | /* User specifies base address explicitly. */ | ||
113 | if (!memblock_is_region_memory(crash_base, crash_size)) { | ||
114 | pr_warn("cannot reserve crashkernel: region is not memory\n"); | ||
115 | return; | ||
116 | } | ||
117 | |||
118 | if (memblock_is_region_reserved(crash_base, crash_size)) { | ||
119 | pr_warn("cannot reserve crashkernel: region overlaps reserved memory\n"); | ||
120 | return; | ||
121 | } | ||
122 | |||
123 | if (!IS_ALIGNED(crash_base, SZ_2M)) { | ||
124 | pr_warn("cannot reserve crashkernel: base address is not 2MB aligned\n"); | ||
125 | return; | ||
126 | } | ||
127 | } | ||
128 | memblock_reserve(crash_base, crash_size); | ||
129 | |||
130 | pr_info("crashkernel reserved: 0x%016llx - 0x%016llx (%lld MB)\n", | ||
131 | crash_base, crash_base + crash_size, crash_size >> 20); | ||
132 | |||
133 | crashk_res.start = crash_base; | ||
134 | crashk_res.end = crash_base + crash_size - 1; | ||
135 | } | ||
136 | |||
137 | static void __init kexec_reserve_crashkres_pages(void) | ||
138 | { | ||
139 | #ifdef CONFIG_HIBERNATION | ||
140 | phys_addr_t addr; | ||
141 | struct page *page; | ||
142 | |||
143 | if (!crashk_res.end) | ||
144 | return; | ||
145 | |||
146 | /* | ||
147 | * To reduce the size of hibernation image, all the pages are | ||
148 | * marked as Reserved initially. | ||
149 | */ | ||
150 | for (addr = crashk_res.start; addr < (crashk_res.end + 1); | ||
151 | addr += PAGE_SIZE) { | ||
152 | page = phys_to_page(addr); | ||
153 | SetPageReserved(page); | ||
154 | } | ||
155 | #endif | ||
156 | } | ||
157 | #else | ||
158 | static void __init reserve_crashkernel(void) | ||
159 | { | ||
160 | } | ||
161 | |||
162 | static void __init kexec_reserve_crashkres_pages(void) | ||
163 | { | ||
164 | } | ||
165 | #endif /* CONFIG_KEXEC_CORE */ | ||
166 | |||
167 | #ifdef CONFIG_CRASH_DUMP | ||
168 | static int __init early_init_dt_scan_elfcorehdr(unsigned long node, | ||
169 | const char *uname, int depth, void *data) | ||
170 | { | ||
171 | const __be32 *reg; | ||
172 | int len; | ||
173 | |||
174 | if (depth != 1 || strcmp(uname, "chosen") != 0) | ||
175 | return 0; | ||
176 | |||
177 | reg = of_get_flat_dt_prop(node, "linux,elfcorehdr", &len); | ||
178 | if (!reg || (len < (dt_root_addr_cells + dt_root_size_cells))) | ||
179 | return 1; | ||
180 | |||
181 | elfcorehdr_addr = dt_mem_next_cell(dt_root_addr_cells, ®); | ||
182 | elfcorehdr_size = dt_mem_next_cell(dt_root_size_cells, ®); | ||
183 | |||
184 | return 1; | ||
185 | } | ||
186 | |||
187 | /* | ||
188 | * reserve_elfcorehdr() - reserves memory for elf core header | ||
189 | * | ||
190 | * This function reserves the memory occupied by an elf core header | ||
191 | * described in the device tree. This region contains all the | ||
192 | * information about primary kernel's core image and is used by a dump | ||
193 | * capture kernel to access the system memory on primary kernel. | ||
194 | */ | ||
195 | static void __init reserve_elfcorehdr(void) | ||
196 | { | ||
197 | of_scan_flat_dt(early_init_dt_scan_elfcorehdr, NULL); | ||
198 | |||
199 | if (!elfcorehdr_size) | ||
200 | return; | ||
201 | |||
202 | if (memblock_is_region_reserved(elfcorehdr_addr, elfcorehdr_size)) { | ||
203 | pr_warn("elfcorehdr is overlapped\n"); | ||
204 | return; | ||
205 | } | ||
206 | |||
207 | memblock_reserve(elfcorehdr_addr, elfcorehdr_size); | ||
208 | |||
209 | pr_info("Reserving %lldKB of memory at 0x%llx for elfcorehdr\n", | ||
210 | elfcorehdr_size >> 10, elfcorehdr_addr); | ||
211 | } | ||
212 | #else | ||
213 | static void __init reserve_elfcorehdr(void) | ||
214 | { | ||
215 | } | ||
216 | #endif /* CONFIG_CRASH_DUMP */ | ||
78 | /* | 217 | /* |
79 | * Return the maximum physical address for ZONE_DMA (DMA_BIT_MASK(32)). It | 218 | * Return the maximum physical address for ZONE_DMA (DMA_BIT_MASK(32)). It |
80 | * currently assumes that for memory starting above 4G, 32-bit devices will | 219 | * currently assumes that for memory starting above 4G, 32-bit devices will |
@@ -168,10 +307,45 @@ static int __init early_mem(char *p) | |||
168 | } | 307 | } |
169 | early_param("mem", early_mem); | 308 | early_param("mem", early_mem); |
170 | 309 | ||
310 | static int __init early_init_dt_scan_usablemem(unsigned long node, | ||
311 | const char *uname, int depth, void *data) | ||
312 | { | ||
313 | struct memblock_region *usablemem = data; | ||
314 | const __be32 *reg; | ||
315 | int len; | ||
316 | |||
317 | if (depth != 1 || strcmp(uname, "chosen") != 0) | ||
318 | return 0; | ||
319 | |||
320 | reg = of_get_flat_dt_prop(node, "linux,usable-memory-range", &len); | ||
321 | if (!reg || (len < (dt_root_addr_cells + dt_root_size_cells))) | ||
322 | return 1; | ||
323 | |||
324 | usablemem->base = dt_mem_next_cell(dt_root_addr_cells, ®); | ||
325 | usablemem->size = dt_mem_next_cell(dt_root_size_cells, ®); | ||
326 | |||
327 | return 1; | ||
328 | } | ||
329 | |||
330 | static void __init fdt_enforce_memory_region(void) | ||
331 | { | ||
332 | struct memblock_region reg = { | ||
333 | .size = 0, | ||
334 | }; | ||
335 | |||
336 | of_scan_flat_dt(early_init_dt_scan_usablemem, ®); | ||
337 | |||
338 | if (reg.size) | ||
339 | memblock_cap_memory_range(reg.base, reg.size); | ||
340 | } | ||
341 | |||
171 | void __init arm64_memblock_init(void) | 342 | void __init arm64_memblock_init(void) |
172 | { | 343 | { |
173 | const s64 linear_region_size = -(s64)PAGE_OFFSET; | 344 | const s64 linear_region_size = -(s64)PAGE_OFFSET; |
174 | 345 | ||
346 | /* Handle linux,usable-memory-range property */ | ||
347 | fdt_enforce_memory_region(); | ||
348 | |||
175 | /* | 349 | /* |
176 | * Ensure that the linear region takes up exactly half of the kernel | 350 | * Ensure that the linear region takes up exactly half of the kernel |
177 | * virtual address space. This way, we can distinguish a linear address | 351 | * virtual address space. This way, we can distinguish a linear address |
@@ -248,6 +422,11 @@ void __init arm64_memblock_init(void) | |||
248 | arm64_dma_phys_limit = max_zone_dma_phys(); | 422 | arm64_dma_phys_limit = max_zone_dma_phys(); |
249 | else | 423 | else |
250 | arm64_dma_phys_limit = PHYS_MASK + 1; | 424 | arm64_dma_phys_limit = PHYS_MASK + 1; |
425 | |||
426 | reserve_crashkernel(); | ||
427 | |||
428 | reserve_elfcorehdr(); | ||
429 | |||
251 | dma_contiguous_reserve(arm64_dma_phys_limit); | 430 | dma_contiguous_reserve(arm64_dma_phys_limit); |
252 | 431 | ||
253 | memblock_allow_resize(); | 432 | memblock_allow_resize(); |
@@ -361,6 +540,8 @@ void __init mem_init(void) | |||
361 | /* this will put all unused low memory onto the freelists */ | 540 | /* this will put all unused low memory onto the freelists */ |
362 | free_all_bootmem(); | 541 | free_all_bootmem(); |
363 | 542 | ||
543 | kexec_reserve_crashkres_pages(); | ||
544 | |||
364 | mem_init_print_info(NULL); | 545 | mem_init_print_info(NULL); |
365 | 546 | ||
366 | #define MLK(b, t) b, t, ((t) - (b)) >> 10 | 547 | #define MLK(b, t) b, t, ((t) - (b)) >> 10 |
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index 1cab2703f5a8..aeadc2c0a6c8 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/errno.h> | 22 | #include <linux/errno.h> |
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/ioport.h> | ||
25 | #include <linux/kexec.h> | ||
24 | #include <linux/libfdt.h> | 26 | #include <linux/libfdt.h> |
25 | #include <linux/mman.h> | 27 | #include <linux/mman.h> |
26 | #include <linux/nodemask.h> | 28 | #include <linux/nodemask.h> |
@@ -156,29 +158,10 @@ static void split_pud(pud_t *old_pud, pmd_t *pmd) | |||
156 | } while (pmd++, i++, i < PTRS_PER_PMD); | 158 | } while (pmd++, i++, i < PTRS_PER_PMD); |
157 | } | 159 | } |
158 | 160 | ||
159 | #ifdef CONFIG_DEBUG_PAGEALLOC | ||
160 | static bool block_mappings_allowed(phys_addr_t (*pgtable_alloc)(void)) | ||
161 | { | ||
162 | |||
163 | /* | ||
164 | * If debug_page_alloc is enabled we must map the linear map | ||
165 | * using pages. However, other mappings created by | ||
166 | * create_mapping_noalloc must use sections in some cases. Allow | ||
167 | * sections to be used in those cases, where no pgtable_alloc | ||
168 | * function is provided. | ||
169 | */ | ||
170 | return !pgtable_alloc || !debug_pagealloc_enabled(); | ||
171 | } | ||
172 | #else | ||
173 | static bool block_mappings_allowed(phys_addr_t (*pgtable_alloc)(void)) | ||
174 | { | ||
175 | return true; | ||
176 | } | ||
177 | #endif | ||
178 | |||
179 | static void alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end, | 161 | static void alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end, |
180 | phys_addr_t phys, pgprot_t prot, | 162 | phys_addr_t phys, pgprot_t prot, |
181 | phys_addr_t (*pgtable_alloc)(void)) | 163 | phys_addr_t (*pgtable_alloc)(void), |
164 | bool allow_block_mappings) | ||
182 | { | 165 | { |
183 | pmd_t *pmd; | 166 | pmd_t *pmd; |
184 | unsigned long next; | 167 | unsigned long next; |
@@ -209,7 +192,7 @@ static void alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end, | |||
209 | next = pmd_addr_end(addr, end); | 192 | next = pmd_addr_end(addr, end); |
210 | /* try section mapping first */ | 193 | /* try section mapping first */ |
211 | if (((addr | next | phys) & ~SECTION_MASK) == 0 && | 194 | if (((addr | next | phys) & ~SECTION_MASK) == 0 && |
212 | block_mappings_allowed(pgtable_alloc)) { | 195 | (!pgtable_alloc || allow_block_mappings)) { |
213 | pmd_t old_pmd =*pmd; | 196 | pmd_t old_pmd =*pmd; |
214 | pmd_set_huge(pmd, phys, prot); | 197 | pmd_set_huge(pmd, phys, prot); |
215 | /* | 198 | /* |
@@ -248,7 +231,8 @@ static inline bool use_1G_block(unsigned long addr, unsigned long next, | |||
248 | 231 | ||
249 | static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end, | 232 | static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end, |
250 | phys_addr_t phys, pgprot_t prot, | 233 | phys_addr_t phys, pgprot_t prot, |
251 | phys_addr_t (*pgtable_alloc)(void)) | 234 | phys_addr_t (*pgtable_alloc)(void), |
235 | bool allow_block_mappings) | ||
252 | { | 236 | { |
253 | pud_t *pud; | 237 | pud_t *pud; |
254 | unsigned long next; | 238 | unsigned long next; |
@@ -269,7 +253,7 @@ static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end, | |||
269 | * For 4K granule only, attempt to put down a 1GB block | 253 | * For 4K granule only, attempt to put down a 1GB block |
270 | */ | 254 | */ |
271 | if (use_1G_block(addr, next, phys) && | 255 | if (use_1G_block(addr, next, phys) && |
272 | block_mappings_allowed(pgtable_alloc)) { | 256 | (!pgtable_alloc || allow_block_mappings)) { |
273 | pud_t old_pud = *pud; | 257 | pud_t old_pud = *pud; |
274 | pud_set_huge(pud, phys, prot); | 258 | pud_set_huge(pud, phys, prot); |
275 | 259 | ||
@@ -290,7 +274,7 @@ static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end, | |||
290 | } | 274 | } |
291 | } else { | 275 | } else { |
292 | alloc_init_pmd(pud, addr, next, phys, prot, | 276 | alloc_init_pmd(pud, addr, next, phys, prot, |
293 | pgtable_alloc); | 277 | pgtable_alloc, allow_block_mappings); |
294 | } | 278 | } |
295 | phys += next - addr; | 279 | phys += next - addr; |
296 | } while (pud++, addr = next, addr != end); | 280 | } while (pud++, addr = next, addr != end); |
@@ -304,7 +288,8 @@ static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end, | |||
304 | */ | 288 | */ |
305 | static void init_pgd(pgd_t *pgd, phys_addr_t phys, unsigned long virt, | 289 | static void init_pgd(pgd_t *pgd, phys_addr_t phys, unsigned long virt, |
306 | phys_addr_t size, pgprot_t prot, | 290 | phys_addr_t size, pgprot_t prot, |
307 | phys_addr_t (*pgtable_alloc)(void)) | 291 | phys_addr_t (*pgtable_alloc)(void), |
292 | bool allow_block_mappings) | ||
308 | { | 293 | { |
309 | unsigned long addr, length, end, next; | 294 | unsigned long addr, length, end, next; |
310 | 295 | ||
@@ -322,7 +307,8 @@ static void init_pgd(pgd_t *pgd, phys_addr_t phys, unsigned long virt, | |||
322 | end = addr + length; | 307 | end = addr + length; |
323 | do { | 308 | do { |
324 | next = pgd_addr_end(addr, end); | 309 | next = pgd_addr_end(addr, end); |
325 | alloc_init_pud(pgd, addr, next, phys, prot, pgtable_alloc); | 310 | alloc_init_pud(pgd, addr, next, phys, prot, pgtable_alloc, |
311 | (!pgtable_alloc || allow_block_mappings)); | ||
326 | phys += next - addr; | 312 | phys += next - addr; |
327 | } while (pgd++, addr = next, addr != end); | 313 | } while (pgd++, addr = next, addr != end); |
328 | } | 314 | } |
@@ -340,9 +326,11 @@ static phys_addr_t late_pgtable_alloc(void) | |||
340 | static void __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys, | 326 | static void __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys, |
341 | unsigned long virt, phys_addr_t size, | 327 | unsigned long virt, phys_addr_t size, |
342 | pgprot_t prot, | 328 | pgprot_t prot, |
343 | phys_addr_t (*alloc)(void)) | 329 | phys_addr_t (*alloc)(void), |
330 | bool allow_block_mappings) | ||
344 | { | 331 | { |
345 | init_pgd(pgd_offset_raw(pgdir, virt), phys, virt, size, prot, alloc); | 332 | init_pgd(pgd_offset_raw(pgdir, virt), phys, virt, size, prot, alloc, |
333 | allow_block_mappings); | ||
346 | } | 334 | } |
347 | 335 | ||
348 | /* | 336 | /* |
@@ -358,16 +346,15 @@ static void __init create_mapping_noalloc(phys_addr_t phys, unsigned long virt, | |||
358 | &phys, virt); | 346 | &phys, virt); |
359 | return; | 347 | return; |
360 | } | 348 | } |
361 | __create_pgd_mapping(init_mm.pgd, phys, virt, size, prot, | 349 | __create_pgd_mapping(init_mm.pgd, phys, virt, size, prot, NULL, true); |
362 | NULL); | ||
363 | } | 350 | } |
364 | 351 | ||
365 | void __init create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys, | 352 | void __init create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys, |
366 | unsigned long virt, phys_addr_t size, | 353 | unsigned long virt, phys_addr_t size, |
367 | pgprot_t prot) | 354 | pgprot_t prot, bool allow_block_mappings) |
368 | { | 355 | { |
369 | __create_pgd_mapping(mm->pgd, phys, virt, size, prot, | 356 | __create_pgd_mapping(mm->pgd, phys, virt, size, prot, |
370 | late_pgtable_alloc); | 357 | late_pgtable_alloc, allow_block_mappings); |
371 | } | 358 | } |
372 | 359 | ||
373 | static void create_mapping_late(phys_addr_t phys, unsigned long virt, | 360 | static void create_mapping_late(phys_addr_t phys, unsigned long virt, |
@@ -380,10 +367,18 @@ static void create_mapping_late(phys_addr_t phys, unsigned long virt, | |||
380 | } | 367 | } |
381 | 368 | ||
382 | __create_pgd_mapping(init_mm.pgd, phys, virt, size, prot, | 369 | __create_pgd_mapping(init_mm.pgd, phys, virt, size, prot, |
383 | late_pgtable_alloc); | 370 | late_pgtable_alloc, !debug_pagealloc_enabled()); |
371 | } | ||
372 | |||
373 | static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, | ||
374 | phys_addr_t end, pgprot_t prot, | ||
375 | bool allow_block_mappings) | ||
376 | { | ||
377 | __create_pgd_mapping(pgd, start, __phys_to_virt(start), end - start, | ||
378 | prot, early_pgtable_alloc, allow_block_mappings); | ||
384 | } | 379 | } |
385 | 380 | ||
386 | static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end) | 381 | static void __init map_mem(pgd_t *pgd) |
387 | { | 382 | { |
388 | unsigned long kernel_start = __pa(_text); | 383 | unsigned long kernel_start = __pa(_text); |
389 | unsigned long kernel_end = __pa(__init_begin); | 384 | unsigned long kernel_end = __pa(__init_begin); |
@@ -391,45 +386,15 @@ static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end | |||
391 | /* | 386 | /* |
392 | * Take care not to create a writable alias for the | 387 | * Take care not to create a writable alias for the |
393 | * read-only text and rodata sections of the kernel image. | 388 | * read-only text and rodata sections of the kernel image. |
389 | * So temporarily mark them as NOMAP to skip mappings in | ||
390 | * the following for-loop | ||
394 | */ | 391 | */ |
395 | 392 | memblock_mark_nomap(kernel_start, kernel_end - kernel_start); | |
396 | /* No overlap with the kernel text/rodata */ | 393 | #ifdef CONFIG_KEXEC_CORE |
397 | if (end < kernel_start || start >= kernel_end) { | 394 | if (crashk_res.end) |
398 | __create_pgd_mapping(pgd, start, __phys_to_virt(start), | 395 | memblock_mark_nomap(crashk_res.start, |
399 | end - start, PAGE_KERNEL, | 396 | resource_size(&crashk_res)); |
400 | early_pgtable_alloc); | 397 | #endif |
401 | return; | ||
402 | } | ||
403 | |||
404 | /* | ||
405 | * This block overlaps the kernel text/rodata mappings. | ||
406 | * Map the portion(s) which don't overlap. | ||
407 | */ | ||
408 | if (start < kernel_start) | ||
409 | __create_pgd_mapping(pgd, start, | ||
410 | __phys_to_virt(start), | ||
411 | kernel_start - start, PAGE_KERNEL, | ||
412 | early_pgtable_alloc); | ||
413 | if (kernel_end < end) | ||
414 | __create_pgd_mapping(pgd, kernel_end, | ||
415 | __phys_to_virt(kernel_end), | ||
416 | end - kernel_end, PAGE_KERNEL, | ||
417 | early_pgtable_alloc); | ||
418 | |||
419 | /* | ||
420 | * Map the linear alias of the [_text, __init_begin) interval as | ||
421 | * read-only/non-executable. This makes the contents of the | ||
422 | * region accessible to subsystems such as hibernate, but | ||
423 | * protects it from inadvertent modification or execution. | ||
424 | */ | ||
425 | __create_pgd_mapping(pgd, kernel_start, __phys_to_virt(kernel_start), | ||
426 | kernel_end - kernel_start, PAGE_KERNEL_RO, | ||
427 | early_pgtable_alloc); | ||
428 | } | ||
429 | |||
430 | static void __init map_mem(pgd_t *pgd) | ||
431 | { | ||
432 | struct memblock_region *reg; | ||
433 | 398 | ||
434 | /* map all the memory banks */ | 399 | /* map all the memory banks */ |
435 | for_each_memblock(memory, reg) { | 400 | for_each_memblock(memory, reg) { |
@@ -441,8 +406,33 @@ static void __init map_mem(pgd_t *pgd) | |||
441 | if (memblock_is_nomap(reg)) | 406 | if (memblock_is_nomap(reg)) |
442 | continue; | 407 | continue; |
443 | 408 | ||
444 | __map_memblock(pgd, start, end); | 409 | __map_memblock(pgd, start, end, |
410 | PAGE_KERNEL, !debug_pagealloc_enabled()); | ||
445 | } | 411 | } |
412 | |||
413 | /* | ||
414 | * Map the linear alias of the [_text, __init_begin) interval as | ||
415 | * read-only/non-executable. This makes the contents of the | ||
416 | * region accessible to subsystems such as hibernate, but | ||
417 | * protects it from inadvertent modification or execution. | ||
418 | */ | ||
419 | __map_memblock(pgd, kernel_start, kernel_end, | ||
420 | PAGE_KERNEL_RO, !debug_pagealloc_enabled()); | ||
421 | memblock_clear_nomap(kernel_start, kernel_end - kernel_start); | ||
422 | |||
423 | #ifdef CONFIG_KEXEC_CORE | ||
424 | /* | ||
425 | * Use page-level mappings here so that we can shrink the region | ||
426 | * in page granularity and put back unused memory to buddy system | ||
427 | * through /sys/kernel/kexec_crash_size interface. | ||
428 | */ | ||
429 | if (crashk_res.end) { | ||
430 | __map_memblock(pgd, crashk_res.start, crashk_res.end + 1, | ||
431 | PAGE_KERNEL, false); | ||
432 | memblock_clear_nomap(crashk_res.start, | ||
433 | resource_size(&crashk_res)); | ||
434 | } | ||
435 | #endif | ||
446 | } | 436 | } |
447 | 437 | ||
448 | void mark_rodata_ro(void) | 438 | void mark_rodata_ro(void) |
@@ -481,7 +471,7 @@ static void __init map_kernel_segment(pgd_t *pgd, void *va_start, void *va_end, | |||
481 | BUG_ON(!PAGE_ALIGNED(size)); | 471 | BUG_ON(!PAGE_ALIGNED(size)); |
482 | 472 | ||
483 | __create_pgd_mapping(pgd, pa_start, (unsigned long)va_start, size, prot, | 473 | __create_pgd_mapping(pgd, pa_start, (unsigned long)va_start, size, prot, |
484 | early_pgtable_alloc); | 474 | early_pgtable_alloc, !debug_pagealloc_enabled()); |
485 | 475 | ||
486 | vma->addr = va_start; | 476 | vma->addr = va_start; |
487 | vma->phys_addr = pa_start; | 477 | vma->phys_addr = pa_start; |
diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c index ca6d268e3313..f4e39dbdd36b 100644 --- a/arch/arm64/mm/pageattr.c +++ b/arch/arm64/mm/pageattr.c | |||
@@ -125,6 +125,19 @@ int set_memory_x(unsigned long addr, int numpages) | |||
125 | } | 125 | } |
126 | EXPORT_SYMBOL_GPL(set_memory_x); | 126 | EXPORT_SYMBOL_GPL(set_memory_x); |
127 | 127 | ||
128 | |||
129 | int set_memory_valid(unsigned long addr, int numpages, int enable) | ||
130 | { | ||
131 | if (enable) | ||
132 | return __change_memory_common(addr, PAGE_SIZE * numpages, | ||
133 | __pgprot(PTE_VALID), | ||
134 | __pgprot(0)); | ||
135 | else | ||
136 | return __change_memory_common(addr, PAGE_SIZE * numpages, | ||
137 | __pgprot(0), | ||
138 | __pgprot(PTE_VALID)); | ||
139 | } | ||
140 | |||
128 | #ifdef CONFIG_DEBUG_PAGEALLOC | 141 | #ifdef CONFIG_DEBUG_PAGEALLOC |
129 | void __kernel_map_pages(struct page *page, int numpages, int enable) | 142 | void __kernel_map_pages(struct page *page, int numpages, int enable) |
130 | { | 143 | { |
diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h index ea6579f48f9d..db71448b9bb9 100644 --- a/arch/powerpc/include/asm/uaccess.h +++ b/arch/powerpc/include/asm/uaccess.h | |||
@@ -327,7 +327,6 @@ static inline unsigned long copy_from_user(void *to, | |||
327 | check_object_size(to, n, false); | 327 | check_object_size(to, n, false); |
328 | return __copy_tofrom_user((__force void __user *)to, from, n); | 328 | return __copy_tofrom_user((__force void __user *)to, from, n); |
329 | } | 329 | } |
330 | |||
331 | memset(to, 0, n); | 330 | memset(to, 0, n); |
332 | return n; | 331 | return n; |
333 | } | 332 | } |
@@ -339,7 +338,6 @@ static inline unsigned long copy_to_user(void __user *to, | |||
339 | check_object_size(from, n, true); | 338 | check_object_size(from, n, true); |
340 | return __copy_tofrom_user(to, (__force void __user *)from, n); | 339 | return __copy_tofrom_user(to, (__force void __user *)from, n); |
341 | } | 340 | } |
342 | |||
343 | return n; | 341 | return n; |
344 | } | 342 | } |
345 | 343 | ||
diff --git a/drivers/base/dma-coherent.c b/drivers/base/dma-coherent.c index 55b83983a9c0..c76eea0c5d12 100644 --- a/drivers/base/dma-coherent.c +++ b/drivers/base/dma-coherent.c | |||
@@ -140,11 +140,35 @@ EXPORT_SYMBOL(dma_mark_declared_memory_occupied); | |||
140 | /** | 140 | /** |
141 | * dma_alloc_from_coherent() - try to allocate memory from the per-device coherent area | 141 | * dma_alloc_from_coherent() - try to allocate memory from the per-device coherent area |
142 | * | 142 | * |
143 | * @dev: device from which we allocate memory | ||
144 | * @size: size of requested memory area | ||
145 | * @dma_handle: This will be filled with the correct dma handle | ||
146 | * @ret: This pointer will be filled with the virtual address | ||
147 | * to allocated area. | ||
148 | * | ||
149 | * This function should be only called from per-arch dma_alloc_coherent() | ||
150 | * to support allocation from per-device coherent memory pools. | ||
151 | * | ||
152 | * Returns 0 if dma_alloc_coherent should continue with allocating from | ||
153 | * generic memory areas, or !0 if dma_alloc_coherent should return @ret. | ||
154 | */ | ||
155 | int dma_alloc_from_coherent(struct device *dev, ssize_t size, | ||
156 | dma_addr_t *dma_handle, void **ret) | ||
157 | { | ||
158 | return dma_malloc_from_coherent(dev, size, dma_handle, ret, true); | ||
159 | } | ||
160 | EXPORT_SYMBOL(dma_alloc_from_coherent); | ||
161 | |||
162 | /** | ||
163 | * dma_malloc_from_coherent() - try to allocate memory from the per-device | ||
164 | * coherent area with option to zero memory | ||
165 | * | ||
143 | * @dev: device from which we allocate memory | 166 | * @dev: device from which we allocate memory |
144 | * @size: size of requested memory area | 167 | * @size: size of requested memory area |
145 | * @dma_handle: This will be filled with the correct dma handle | 168 | * @dma_handle: This will be filled with the correct dma handle |
146 | * @ret: This pointer will be filled with the virtual address | 169 | * @ret: This pointer will be filled with the virtual address |
147 | * to allocated area. | 170 | * to allocated area. |
171 | * @zero: should the memory be zero-ed or not | ||
148 | * | 172 | * |
149 | * This function should be only called from per-arch dma_alloc_coherent() | 173 | * This function should be only called from per-arch dma_alloc_coherent() |
150 | * to support allocation from per-device coherent memory pools. | 174 | * to support allocation from per-device coherent memory pools. |
@@ -152,8 +176,9 @@ EXPORT_SYMBOL(dma_mark_declared_memory_occupied); | |||
152 | * Returns 0 if dma_alloc_coherent should continue with allocating from | 176 | * Returns 0 if dma_alloc_coherent should continue with allocating from |
153 | * generic memory areas, or !0 if dma_alloc_coherent should return @ret. | 177 | * generic memory areas, or !0 if dma_alloc_coherent should return @ret. |
154 | */ | 178 | */ |
155 | int dma_alloc_from_coherent(struct device *dev, ssize_t size, | 179 | int dma_malloc_from_coherent(struct device *dev, ssize_t size, |
156 | dma_addr_t *dma_handle, void **ret) | 180 | dma_addr_t *dma_handle, void **ret, |
181 | bool zero) | ||
157 | { | 182 | { |
158 | struct dma_coherent_mem *mem; | 183 | struct dma_coherent_mem *mem; |
159 | int order = get_order(size); | 184 | int order = get_order(size); |
@@ -181,7 +206,8 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size, | |||
181 | */ | 206 | */ |
182 | *dma_handle = mem->device_base + (pageno << PAGE_SHIFT); | 207 | *dma_handle = mem->device_base + (pageno << PAGE_SHIFT); |
183 | *ret = mem->virt_base + (pageno << PAGE_SHIFT); | 208 | *ret = mem->virt_base + (pageno << PAGE_SHIFT); |
184 | memset(*ret, 0, size); | 209 | if (zero) |
210 | memset(*ret, 0, size); | ||
185 | spin_unlock_irqrestore(&mem->spinlock, flags); | 211 | spin_unlock_irqrestore(&mem->spinlock, flags); |
186 | 212 | ||
187 | return 1; | 213 | return 1; |
@@ -195,7 +221,7 @@ err: | |||
195 | */ | 221 | */ |
196 | return mem->flags & DMA_MEMORY_EXCLUSIVE; | 222 | return mem->flags & DMA_MEMORY_EXCLUSIVE; |
197 | } | 223 | } |
198 | EXPORT_SYMBOL(dma_alloc_from_coherent); | 224 | EXPORT_SYMBOL(dma_malloc_from_coherent); |
199 | 225 | ||
200 | /** | 226 | /** |
201 | * dma_release_from_coherent() - try to free the memory allocated from per-device coherent memory pool | 227 | * dma_release_from_coherent() - try to free the memory allocated from per-device coherent memory pool |
diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c index b1c22cf18f7d..9ee9973b5c3e 100644 --- a/drivers/firmware/efi/libstub/fdt.c +++ b/drivers/firmware/efi/libstub/fdt.c | |||
@@ -16,6 +16,22 @@ | |||
16 | 16 | ||
17 | #include "efistub.h" | 17 | #include "efistub.h" |
18 | 18 | ||
19 | #define EFI_DT_ADDR_CELLS_DEFAULT 2 | ||
20 | #define EFI_DT_SIZE_CELLS_DEFAULT 2 | ||
21 | |||
22 | static void fdt_update_cell_size(efi_system_table_t *sys_table, void *fdt) | ||
23 | { | ||
24 | int offset; | ||
25 | |||
26 | offset = fdt_path_offset(fdt, "/"); | ||
27 | /* Set the #address-cells and #size-cells values for an empty tree */ | ||
28 | |||
29 | fdt_setprop_u32(fdt, offset, "#address-cells", | ||
30 | EFI_DT_ADDR_CELLS_DEFAULT); | ||
31 | |||
32 | fdt_setprop_u32(fdt, offset, "#size-cells", EFI_DT_SIZE_CELLS_DEFAULT); | ||
33 | } | ||
34 | |||
19 | efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, | 35 | efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, |
20 | unsigned long orig_fdt_size, | 36 | unsigned long orig_fdt_size, |
21 | void *fdt, int new_fdt_size, char *cmdline_ptr, | 37 | void *fdt, int new_fdt_size, char *cmdline_ptr, |
@@ -45,10 +61,18 @@ efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, | |||
45 | } | 61 | } |
46 | } | 62 | } |
47 | 63 | ||
48 | if (orig_fdt) | 64 | if (orig_fdt) { |
49 | status = fdt_open_into(orig_fdt, fdt, new_fdt_size); | 65 | status = fdt_open_into(orig_fdt, fdt, new_fdt_size); |
50 | else | 66 | } else { |
51 | status = fdt_create_empty_tree(fdt, new_fdt_size); | 67 | status = fdt_create_empty_tree(fdt, new_fdt_size); |
68 | if (status == 0) { | ||
69 | /* | ||
70 | * Any failure from the following function is non | ||
71 | * critical | ||
72 | */ | ||
73 | fdt_update_cell_size(sys_table, fdt); | ||
74 | } | ||
75 | } | ||
52 | 76 | ||
53 | if (status != 0) | 77 | if (status != 0) |
54 | goto fdt_set_fail; | 78 | goto fdt_set_fail; |
diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c index 4a41694919da..47cc4dcea36e 100644 --- a/drivers/gpio/gpio-mcp23s08.c +++ b/drivers/gpio/gpio-mcp23s08.c | |||
@@ -584,6 +584,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, | |||
584 | struct mcp23s08_platform_data *pdata, int cs) | 584 | struct mcp23s08_platform_data *pdata, int cs) |
585 | { | 585 | { |
586 | int status; | 586 | int status; |
587 | u32 init_dir = 0, init_val = 0; | ||
587 | bool mirror = false; | 588 | bool mirror = false; |
588 | 589 | ||
589 | mutex_init(&mcp->lock); | 590 | mutex_init(&mcp->lock); |
@@ -682,6 +683,14 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, | |||
682 | if (status < 0) | 683 | if (status < 0) |
683 | goto fail; | 684 | goto fail; |
684 | 685 | ||
686 | if (of_property_read_u32(mcp->chip.of_node, | ||
687 | "init-dir", &init_dir) == 0) | ||
688 | status = mcp->ops->write(mcp, MCP_IODIR, init_dir); | ||
689 | |||
690 | if (of_property_read_u32(mcp->chip.of_node, | ||
691 | "init-val", &init_val) == 0) | ||
692 | status = mcp->ops->write(mcp, MCP_OLAT, init_val); | ||
693 | |||
685 | status = mcp->ops->read_regs(mcp, 0, mcp->cache, ARRAY_SIZE(mcp->cache)); | 694 | status = mcp->ops->read_regs(mcp, 0, mcp->cache, ARRAY_SIZE(mcp->cache)); |
686 | if (status < 0) | 695 | if (status < 0) |
687 | goto fail; | 696 | goto fail; |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5044f2257e89..6fca39e1c419 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -3475,11 +3475,6 @@ static inline uint32_t i915_vgacntrl_reg(struct drm_device *dev) | |||
3475 | return VGACNTRL; | 3475 | return VGACNTRL; |
3476 | } | 3476 | } |
3477 | 3477 | ||
3478 | static inline void __user *to_user_ptr(u64 address) | ||
3479 | { | ||
3480 | return (void __user *)(uintptr_t)address; | ||
3481 | } | ||
3482 | |||
3483 | static inline unsigned long msecs_to_jiffies_timeout(const unsigned int m) | 3478 | static inline unsigned long msecs_to_jiffies_timeout(const unsigned int m) |
3484 | { | 3479 | { |
3485 | unsigned long j = msecs_to_jiffies(m); | 3480 | unsigned long j = msecs_to_jiffies(m); |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index f56af0aaafde..659b90657f36 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -324,7 +324,7 @@ i915_gem_phys_pwrite(struct drm_i915_gem_object *obj, | |||
324 | { | 324 | { |
325 | struct drm_device *dev = obj->base.dev; | 325 | struct drm_device *dev = obj->base.dev; |
326 | void *vaddr = obj->phys_handle->vaddr + args->offset; | 326 | void *vaddr = obj->phys_handle->vaddr + args->offset; |
327 | char __user *user_data = to_user_ptr(args->data_ptr); | 327 | char __user *user_data = u64_to_user_ptr(args->data_ptr); |
328 | int ret = 0; | 328 | int ret = 0; |
329 | 329 | ||
330 | /* We manually control the domain here and pretend that it | 330 | /* We manually control the domain here and pretend that it |
@@ -605,7 +605,7 @@ i915_gem_shmem_pread(struct drm_device *dev, | |||
605 | int needs_clflush = 0; | 605 | int needs_clflush = 0; |
606 | struct sg_page_iter sg_iter; | 606 | struct sg_page_iter sg_iter; |
607 | 607 | ||
608 | user_data = to_user_ptr(args->data_ptr); | 608 | user_data = u64_to_user_ptr(args->data_ptr); |
609 | remain = args->size; | 609 | remain = args->size; |
610 | 610 | ||
611 | obj_do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); | 611 | obj_do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); |
@@ -692,7 +692,7 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, | |||
692 | return 0; | 692 | return 0; |
693 | 693 | ||
694 | if (!access_ok(VERIFY_WRITE, | 694 | if (!access_ok(VERIFY_WRITE, |
695 | to_user_ptr(args->data_ptr), | 695 | u64_to_user_ptr(args->data_ptr), |
696 | args->size)) | 696 | args->size)) |
697 | return -EFAULT; | 697 | return -EFAULT; |
698 | 698 | ||
@@ -783,7 +783,7 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev, | |||
783 | if (ret) | 783 | if (ret) |
784 | goto out_unpin; | 784 | goto out_unpin; |
785 | 785 | ||
786 | user_data = to_user_ptr(args->data_ptr); | 786 | user_data = u64_to_user_ptr(args->data_ptr); |
787 | remain = args->size; | 787 | remain = args->size; |
788 | 788 | ||
789 | offset = i915_gem_obj_ggtt_offset(obj) + args->offset; | 789 | offset = i915_gem_obj_ggtt_offset(obj) + args->offset; |
@@ -907,7 +907,7 @@ i915_gem_shmem_pwrite(struct drm_device *dev, | |||
907 | int needs_clflush_before = 0; | 907 | int needs_clflush_before = 0; |
908 | struct sg_page_iter sg_iter; | 908 | struct sg_page_iter sg_iter; |
909 | 909 | ||
910 | user_data = to_user_ptr(args->data_ptr); | 910 | user_data = u64_to_user_ptr(args->data_ptr); |
911 | remain = args->size; | 911 | remain = args->size; |
912 | 912 | ||
913 | obj_do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); | 913 | obj_do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); |
@@ -1036,12 +1036,12 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, | |||
1036 | return 0; | 1036 | return 0; |
1037 | 1037 | ||
1038 | if (!access_ok(VERIFY_READ, | 1038 | if (!access_ok(VERIFY_READ, |
1039 | to_user_ptr(args->data_ptr), | 1039 | u64_to_user_ptr(args->data_ptr), |
1040 | args->size)) | 1040 | args->size)) |
1041 | return -EFAULT; | 1041 | return -EFAULT; |
1042 | 1042 | ||
1043 | if (likely(!i915.prefault_disable)) { | 1043 | if (likely(!i915.prefault_disable)) { |
1044 | ret = fault_in_multipages_readable(to_user_ptr(args->data_ptr), | 1044 | ret = fault_in_multipages_readable(u64_to_user_ptr(args->data_ptr), |
1045 | args->size); | 1045 | args->size); |
1046 | if (ret) | 1046 | if (ret) |
1047 | return -EFAULT; | 1047 | return -EFAULT; |
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 201947b4377c..8800f410b2d2 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c | |||
@@ -492,7 +492,7 @@ i915_gem_execbuffer_relocate_vma(struct i915_vma *vma, | |||
492 | struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; | 492 | struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; |
493 | int remain, ret; | 493 | int remain, ret; |
494 | 494 | ||
495 | user_relocs = to_user_ptr(entry->relocs_ptr); | 495 | user_relocs = u64_to_user_ptr(entry->relocs_ptr); |
496 | 496 | ||
497 | remain = entry->relocation_count; | 497 | remain = entry->relocation_count; |
498 | while (remain) { | 498 | while (remain) { |
@@ -831,7 +831,7 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, | |||
831 | u64 invalid_offset = (u64)-1; | 831 | u64 invalid_offset = (u64)-1; |
832 | int j; | 832 | int j; |
833 | 833 | ||
834 | user_relocs = to_user_ptr(exec[i].relocs_ptr); | 834 | user_relocs = u64_to_user_ptr(exec[i].relocs_ptr); |
835 | 835 | ||
836 | if (copy_from_user(reloc+total, user_relocs, | 836 | if (copy_from_user(reloc+total, user_relocs, |
837 | exec[i].relocation_count * sizeof(*reloc))) { | 837 | exec[i].relocation_count * sizeof(*reloc))) { |
@@ -975,7 +975,7 @@ validate_exec_list(struct drm_device *dev, | |||
975 | invalid_flags |= EXEC_OBJECT_NEEDS_GTT; | 975 | invalid_flags |= EXEC_OBJECT_NEEDS_GTT; |
976 | 976 | ||
977 | for (i = 0; i < count; i++) { | 977 | for (i = 0; i < count; i++) { |
978 | char __user *ptr = to_user_ptr(exec[i].relocs_ptr); | 978 | char __user *ptr = u64_to_user_ptr(exec[i].relocs_ptr); |
979 | int length; /* limited by fault_in_pages_readable() */ | 979 | int length; /* limited by fault_in_pages_readable() */ |
980 | 980 | ||
981 | if (exec[i].flags & invalid_flags) | 981 | if (exec[i].flags & invalid_flags) |
@@ -1633,7 +1633,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
1633 | return -ENOMEM; | 1633 | return -ENOMEM; |
1634 | } | 1634 | } |
1635 | ret = copy_from_user(exec_list, | 1635 | ret = copy_from_user(exec_list, |
1636 | to_user_ptr(args->buffers_ptr), | 1636 | u64_to_user_ptr(args->buffers_ptr), |
1637 | sizeof(*exec_list) * args->buffer_count); | 1637 | sizeof(*exec_list) * args->buffer_count); |
1638 | if (ret != 0) { | 1638 | if (ret != 0) { |
1639 | DRM_DEBUG("copy %d exec entries failed %d\n", | 1639 | DRM_DEBUG("copy %d exec entries failed %d\n", |
@@ -1669,7 +1669,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
1669 | ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list); | 1669 | ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list); |
1670 | if (!ret) { | 1670 | if (!ret) { |
1671 | struct drm_i915_gem_exec_object __user *user_exec_list = | 1671 | struct drm_i915_gem_exec_object __user *user_exec_list = |
1672 | to_user_ptr(args->buffers_ptr); | 1672 | u64_to_user_ptr(args->buffers_ptr); |
1673 | 1673 | ||
1674 | /* Copy the new buffer offsets back to the user's exec list. */ | 1674 | /* Copy the new buffer offsets back to the user's exec list. */ |
1675 | for (i = 0; i < args->buffer_count; i++) { | 1675 | for (i = 0; i < args->buffer_count; i++) { |
@@ -1721,7 +1721,7 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data, | |||
1721 | return -ENOMEM; | 1721 | return -ENOMEM; |
1722 | } | 1722 | } |
1723 | ret = copy_from_user(exec2_list, | 1723 | ret = copy_from_user(exec2_list, |
1724 | to_user_ptr(args->buffers_ptr), | 1724 | u64_to_user_ptr(args->buffers_ptr), |
1725 | sizeof(*exec2_list) * args->buffer_count); | 1725 | sizeof(*exec2_list) * args->buffer_count); |
1726 | if (ret != 0) { | 1726 | if (ret != 0) { |
1727 | DRM_DEBUG("copy %d exec entries failed %d\n", | 1727 | DRM_DEBUG("copy %d exec entries failed %d\n", |
@@ -1734,7 +1734,7 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data, | |||
1734 | if (!ret) { | 1734 | if (!ret) { |
1735 | /* Copy the new buffer offsets back to the user's exec list. */ | 1735 | /* Copy the new buffer offsets back to the user's exec list. */ |
1736 | struct drm_i915_gem_exec_object2 __user *user_exec_list = | 1736 | struct drm_i915_gem_exec_object2 __user *user_exec_list = |
1737 | to_user_ptr(args->buffers_ptr); | 1737 | u64_to_user_ptr(args->buffers_ptr); |
1738 | int i; | 1738 | int i; |
1739 | 1739 | ||
1740 | for (i = 0; i < args->buffer_count; i++) { | 1740 | for (i = 0; i < args->buffer_count; i++) { |
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index fed44d4e5b72..ed1efae0c3f2 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c | |||
@@ -28,11 +28,6 @@ | |||
28 | #define BO_LOCKED 0x4000 | 28 | #define BO_LOCKED 0x4000 |
29 | #define BO_PINNED 0x2000 | 29 | #define BO_PINNED 0x2000 |
30 | 30 | ||
31 | static inline void __user *to_user_ptr(u64 address) | ||
32 | { | ||
33 | return (void __user *)(uintptr_t)address; | ||
34 | } | ||
35 | |||
36 | static struct msm_gem_submit *submit_create(struct drm_device *dev, | 31 | static struct msm_gem_submit *submit_create(struct drm_device *dev, |
37 | struct msm_gpu *gpu, int nr) | 32 | struct msm_gpu *gpu, int nr) |
38 | { | 33 | { |
@@ -77,7 +72,7 @@ static int submit_lookup_objects(struct msm_gem_submit *submit, | |||
77 | struct drm_gem_object *obj; | 72 | struct drm_gem_object *obj; |
78 | struct msm_gem_object *msm_obj; | 73 | struct msm_gem_object *msm_obj; |
79 | void __user *userptr = | 74 | void __user *userptr = |
80 | to_user_ptr(args->bos + (i * sizeof(submit_bo))); | 75 | u64_to_user_ptr(args->bos + (i * sizeof(submit_bo))); |
81 | 76 | ||
82 | ret = copy_from_user_inatomic(&submit_bo, userptr, sizeof(submit_bo)); | 77 | ret = copy_from_user_inatomic(&submit_bo, userptr, sizeof(submit_bo)); |
83 | if (unlikely(ret)) { | 78 | if (unlikely(ret)) { |
@@ -275,7 +270,7 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob | |||
275 | for (i = 0; i < nr_relocs; i++) { | 270 | for (i = 0; i < nr_relocs; i++) { |
276 | struct drm_msm_gem_submit_reloc submit_reloc; | 271 | struct drm_msm_gem_submit_reloc submit_reloc; |
277 | void __user *userptr = | 272 | void __user *userptr = |
278 | to_user_ptr(relocs + (i * sizeof(submit_reloc))); | 273 | u64_to_user_ptr(relocs + (i * sizeof(submit_reloc))); |
279 | uint32_t iova, off; | 274 | uint32_t iova, off; |
280 | bool valid; | 275 | bool valid; |
281 | 276 | ||
@@ -375,7 +370,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, | |||
375 | for (i = 0; i < args->nr_cmds; i++) { | 370 | for (i = 0; i < args->nr_cmds; i++) { |
376 | struct drm_msm_gem_submit_cmd submit_cmd; | 371 | struct drm_msm_gem_submit_cmd submit_cmd; |
377 | void __user *userptr = | 372 | void __user *userptr = |
378 | to_user_ptr(args->cmds + (i * sizeof(submit_cmd))); | 373 | u64_to_user_ptr(args->cmds + (i * sizeof(submit_cmd))); |
379 | struct msm_gem_object *msm_obj; | 374 | struct msm_gem_object *msm_obj; |
380 | uint32_t iova; | 375 | uint32_t iova; |
381 | 376 | ||
diff --git a/drivers/gpu/drm/omapdrm/displays/Makefile b/drivers/gpu/drm/omapdrm/displays/Makefile index 729a00dc3178..d08d40bcfd33 100644 --- a/drivers/gpu/drm/omapdrm/displays/Makefile +++ b/drivers/gpu/drm/omapdrm/displays/Makefile | |||
@@ -1,3 +1,6 @@ | |||
1 | obj-$(CONFIG_DISPLAY_ENCODER_TC358768) += encoder-tc358768.o | ||
2 | obj-$(CONFIG_DISPLAY_PANEL_TLC59108) += panel-tlc59108.o | ||
3 | obj-$(CONFIG_DISPLAY_PANEL_DPI) += panel-dpi.o | ||
1 | obj-$(CONFIG_DISPLAY_ENCODER_OPA362) += encoder-opa362.o | 4 | obj-$(CONFIG_DISPLAY_ENCODER_OPA362) += encoder-opa362.o |
2 | obj-$(CONFIG_DISPLAY_ENCODER_TFP410) += encoder-tfp410.o | 5 | obj-$(CONFIG_DISPLAY_ENCODER_TFP410) += encoder-tfp410.o |
3 | obj-$(CONFIG_DISPLAY_ENCODER_TPD12S015) += encoder-tpd12s015.o | 6 | obj-$(CONFIG_DISPLAY_ENCODER_TPD12S015) += encoder-tpd12s015.o |
@@ -5,11 +8,9 @@ obj-$(CONFIG_DISPLAY_DRA7EVM_ENCODER_TPD12S015) += dra7-evm-encoder-tpd12s015.o | |||
5 | obj-$(CONFIG_DISPLAY_ENCODER_SII9022) += encoder-sii9022.o | 8 | obj-$(CONFIG_DISPLAY_ENCODER_SII9022) += encoder-sii9022.o |
6 | encoder-sii9022-y += encoder-sii9022-video.o | 9 | encoder-sii9022-y += encoder-sii9022-video.o |
7 | encoder-sii9022-$(CONFIG_DISPLAY_ENCODER_SII9022_AUDIO_CODEC) += encoder-sii9022-audio.o | 10 | encoder-sii9022-$(CONFIG_DISPLAY_ENCODER_SII9022_AUDIO_CODEC) += encoder-sii9022-audio.o |
8 | obj-$(CONFIG_DISPLAY_ENCODER_TC358768) += encoder-tc358768.o | ||
9 | obj-$(CONFIG_DISPLAY_CONNECTOR_DVI) += connector-dvi.o | 11 | obj-$(CONFIG_DISPLAY_CONNECTOR_DVI) += connector-dvi.o |
10 | obj-$(CONFIG_DISPLAY_CONNECTOR_HDMI) += connector-hdmi.o | 12 | obj-$(CONFIG_DISPLAY_CONNECTOR_HDMI) += connector-hdmi.o |
11 | obj-$(CONFIG_DISPLAY_CONNECTOR_ANALOG_TV) += connector-analog-tv.o | 13 | obj-$(CONFIG_DISPLAY_CONNECTOR_ANALOG_TV) += connector-analog-tv.o |
12 | obj-$(CONFIG_DISPLAY_PANEL_DPI) += panel-dpi.o | ||
13 | obj-$(CONFIG_DISPLAY_PANEL_DSI_CM) += panel-dsi-cm.o | 14 | obj-$(CONFIG_DISPLAY_PANEL_DSI_CM) += panel-dsi-cm.o |
14 | obj-$(CONFIG_DISPLAY_PANEL_SONY_ACX565AKM) += panel-sony-acx565akm.o | 15 | obj-$(CONFIG_DISPLAY_PANEL_SONY_ACX565AKM) += panel-sony-acx565akm.o |
15 | obj-$(CONFIG_DISPLAY_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o | 16 | obj-$(CONFIG_DISPLAY_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o |
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c index c30ce05dff3d..d717079a122f 100644 --- a/drivers/gpu/drm/omapdrm/omap_connector.c +++ b/drivers/gpu/drm/omapdrm/omap_connector.c | |||
@@ -352,6 +352,11 @@ struct drm_connector *omap_connector_init(struct drm_device *dev, | |||
352 | connector_type); | 352 | connector_type); |
353 | drm_connector_helper_add(connector, &omap_connector_helper_funcs); | 353 | drm_connector_helper_add(connector, &omap_connector_helper_funcs); |
354 | 354 | ||
355 | #if 0 /* enable when dss2 supports hotplug */ | ||
356 | if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_HPD) | ||
357 | connector->polled = 0; | ||
358 | else | ||
359 | #endif | ||
355 | if (dssdev->driver->enable_hpd) { | 360 | if (dssdev->driver->enable_hpd) { |
356 | int ret = dssdev->driver->enable_hpd(dssdev, | 361 | int ret = dssdev->driver->enable_hpd(dssdev, |
357 | omap_connector_hpd_cb, | 362 | omap_connector_hpd_cb, |
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index 8dfeebec8c6c..82ba6dc9fc7c 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h | |||
@@ -233,6 +233,8 @@ void omap_gem_put_paddr(struct drm_gem_object *obj); | |||
233 | int omap_gem_get_pages(struct drm_gem_object *obj, struct page ***pages, | 233 | int omap_gem_get_pages(struct drm_gem_object *obj, struct page ***pages, |
234 | bool remap); | 234 | bool remap); |
235 | int omap_gem_put_pages(struct drm_gem_object *obj); | 235 | int omap_gem_put_pages(struct drm_gem_object *obj); |
236 | struct sg_table *omap_gem_get_sgt(struct drm_gem_object *obj); | ||
237 | void omap_gem_put_sgt(struct drm_gem_object *obj, struct sg_table *sg); | ||
236 | uint32_t omap_gem_flags(struct drm_gem_object *obj); | 238 | uint32_t omap_gem_flags(struct drm_gem_object *obj); |
237 | int omap_gem_rotated_paddr(struct drm_gem_object *obj, uint32_t orient, | 239 | int omap_gem_rotated_paddr(struct drm_gem_object *obj, uint32_t orient, |
238 | int x, int y, dma_addr_t *paddr); | 240 | int x, int y, dma_addr_t *paddr); |
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index 746803476d6d..6ec7916e3840 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c | |||
@@ -666,7 +666,8 @@ int omap_gem_dumb_create(struct drm_file *file, struct drm_device *dev, | |||
666 | }; | 666 | }; |
667 | 667 | ||
668 | return omap_gem_new_handle(dev, file, gsize, | 668 | return omap_gem_new_handle(dev, file, gsize, |
669 | OMAP_BO_SCANOUT | OMAP_BO_WC, &args->handle); | 669 | OMAP_BO_SCANOUT | OMAP_BO_WC | args->flags, |
670 | &args->handle); | ||
670 | } | 671 | } |
671 | 672 | ||
672 | /** | 673 | /** |
@@ -807,6 +808,68 @@ void omap_gem_dma_sync(struct drm_gem_object *obj, | |||
807 | } | 808 | } |
808 | } | 809 | } |
809 | 810 | ||
811 | struct sg_table *omap_gem_get_sgt(struct drm_gem_object *obj) | ||
812 | { | ||
813 | struct omap_gem_object *omap_obj = to_omap_bo(obj); | ||
814 | struct sg_table *sg; | ||
815 | dma_addr_t paddr; | ||
816 | int ret; | ||
817 | bool remap; | ||
818 | |||
819 | remap = omap_obj->flags & OMAP_BO_SCANOUT; | ||
820 | ret = omap_gem_get_paddr(obj, &paddr, remap); | ||
821 | if (ret) | ||
822 | goto out; | ||
823 | |||
824 | sg = kmalloc(sizeof(*sg), GFP_KERNEL); | ||
825 | if (!sg) | ||
826 | return NULL; | ||
827 | |||
828 | if (omap_obj->paddr) { | ||
829 | if (sg_alloc_table(sg, 1, GFP_KERNEL)) | ||
830 | goto free; | ||
831 | |||
832 | sg_init_table(sg->sgl, 1); | ||
833 | sg_dma_len(sg->sgl) = obj->size; | ||
834 | sg_set_page(sg->sgl, pfn_to_page(PFN_DOWN(omap_obj->paddr)), | ||
835 | obj->size, 0); | ||
836 | sg_dma_address(sg->sgl) = omap_obj->paddr; | ||
837 | } else if (omap_obj->pages) { | ||
838 | struct scatterlist *sgl; | ||
839 | unsigned int i = 0; | ||
840 | int npages = obj->size >> PAGE_SHIFT; | ||
841 | |||
842 | if (sg_alloc_table(sg, npages, GFP_KERNEL)) | ||
843 | goto free; | ||
844 | |||
845 | for_each_sg(sg->sgl, sgl, npages, i) { | ||
846 | sg_set_page(sgl, omap_obj->pages[i], PAGE_SIZE, 0); | ||
847 | sg_dma_address(sgl) = omap_obj->addrs[i]; | ||
848 | sg_dma_len(sgl) = PAGE_SIZE; | ||
849 | } | ||
850 | } else { | ||
851 | /* we should have had paddr or pages here */ | ||
852 | goto free; | ||
853 | } | ||
854 | return sg; | ||
855 | |||
856 | out: | ||
857 | return ERR_PTR(ret); | ||
858 | free: | ||
859 | sg_free_table(sg); | ||
860 | kfree(sg); | ||
861 | return NULL; | ||
862 | } | ||
863 | |||
864 | void omap_gem_put_sgt(struct drm_gem_object *obj, struct sg_table *sg) | ||
865 | { | ||
866 | struct omap_gem_object *omap_obj = to_omap_bo(obj); | ||
867 | bool remap = omap_obj->flags & OMAP_BO_SCANOUT; | ||
868 | |||
869 | if (remap) | ||
870 | omap_gem_put_paddr(obj); | ||
871 | } | ||
872 | |||
810 | /* Get physical address for DMA.. if 'remap' is true, and the buffer is not | 873 | /* Get physical address for DMA.. if 'remap' is true, and the buffer is not |
811 | * already contiguous, remap it to pin in physically contiguous memory.. (ie. | 874 | * already contiguous, remap it to pin in physically contiguous memory.. (ie. |
812 | * map in TILER) | 875 | * map in TILER) |
@@ -820,19 +883,22 @@ int omap_gem_get_paddr(struct drm_gem_object *obj, | |||
820 | 883 | ||
821 | mutex_lock(&obj->dev->struct_mutex); | 884 | mutex_lock(&obj->dev->struct_mutex); |
822 | 885 | ||
823 | if (!is_contiguous(omap_obj) && remap && priv->has_dmm) { | 886 | if (!is_contiguous(omap_obj)) { |
824 | if (omap_obj->paddr_cnt == 0) { | 887 | struct page **pages; |
825 | struct page **pages; | 888 | uint32_t npages = obj->size >> PAGE_SHIFT; |
826 | uint32_t npages = obj->size >> PAGE_SHIFT; | 889 | |
890 | ret = get_pages(obj, &pages); | ||
891 | if (ret) | ||
892 | goto fail; | ||
893 | |||
894 | if ((omap_obj->paddr_cnt == 0) && | ||
895 | ((omap_obj->flags & OMAP_BO_SCANOUT) || remap) && | ||
896 | priv->has_dmm) { | ||
827 | enum tiler_fmt fmt = gem2fmt(omap_obj->flags); | 897 | enum tiler_fmt fmt = gem2fmt(omap_obj->flags); |
828 | struct tiler_block *block; | 898 | struct tiler_block *block; |
829 | 899 | ||
830 | BUG_ON(omap_obj->block); | 900 | BUG_ON(omap_obj->block); |
831 | 901 | ||
832 | ret = get_pages(obj, &pages); | ||
833 | if (ret) | ||
834 | goto fail; | ||
835 | |||
836 | if (omap_obj->flags & OMAP_BO_TILED) { | 902 | if (omap_obj->flags & OMAP_BO_TILED) { |
837 | block = tiler_reserve_2d(fmt, | 903 | block = tiler_reserve_2d(fmt, |
838 | omap_obj->width, | 904 | omap_obj->width, |
@@ -861,12 +927,12 @@ int omap_gem_get_paddr(struct drm_gem_object *obj, | |||
861 | omap_obj->paddr = tiler_ssptr(block); | 927 | omap_obj->paddr = tiler_ssptr(block); |
862 | omap_obj->block = block; | 928 | omap_obj->block = block; |
863 | 929 | ||
864 | DBG("got paddr: %pad", &omap_obj->paddr); | 930 | omap_obj->paddr_cnt++; |
931 | *paddr = omap_obj->paddr; | ||
932 | } else if (omap_obj->paddr_cnt > 0) { | ||
933 | omap_obj->paddr_cnt++; | ||
934 | *paddr = omap_obj->paddr; | ||
865 | } | 935 | } |
866 | |||
867 | omap_obj->paddr_cnt++; | ||
868 | |||
869 | *paddr = omap_obj->paddr; | ||
870 | } else if (is_contiguous(omap_obj)) { | 936 | } else if (is_contiguous(omap_obj)) { |
871 | *paddr = omap_obj->paddr; | 937 | *paddr = omap_obj->paddr; |
872 | } else { | 938 | } else { |
@@ -883,12 +949,12 @@ fail: | |||
883 | /* Release physical address, when DMA is no longer being performed.. this | 949 | /* Release physical address, when DMA is no longer being performed.. this |
884 | * could potentially unpin and unmap buffers from TILER | 950 | * could potentially unpin and unmap buffers from TILER |
885 | */ | 951 | */ |
886 | void omap_gem_put_paddr(struct drm_gem_object *obj) | 952 | |
953 | static void omap_gem_put_paddr_locked(struct drm_gem_object *obj) | ||
887 | { | 954 | { |
888 | struct omap_gem_object *omap_obj = to_omap_bo(obj); | 955 | struct omap_gem_object *omap_obj = to_omap_bo(obj); |
889 | int ret; | 956 | int ret; |
890 | 957 | ||
891 | mutex_lock(&obj->dev->struct_mutex); | ||
892 | if (omap_obj->paddr_cnt > 0) { | 958 | if (omap_obj->paddr_cnt > 0) { |
893 | omap_obj->paddr_cnt--; | 959 | omap_obj->paddr_cnt--; |
894 | if (omap_obj->paddr_cnt == 0) { | 960 | if (omap_obj->paddr_cnt == 0) { |
@@ -906,7 +972,12 @@ void omap_gem_put_paddr(struct drm_gem_object *obj) | |||
906 | omap_obj->block = NULL; | 972 | omap_obj->block = NULL; |
907 | } | 973 | } |
908 | } | 974 | } |
975 | } | ||
909 | 976 | ||
977 | void omap_gem_put_paddr(struct drm_gem_object *obj) | ||
978 | { | ||
979 | mutex_lock(&obj->dev->struct_mutex); | ||
980 | omap_gem_put_paddr_locked(obj); | ||
910 | mutex_unlock(&obj->dev->struct_mutex); | 981 | mutex_unlock(&obj->dev->struct_mutex); |
911 | } | 982 | } |
912 | 983 | ||
@@ -1298,6 +1369,9 @@ void omap_gem_free_object(struct drm_gem_object *obj) | |||
1298 | list_del(&omap_obj->mm_list); | 1369 | list_del(&omap_obj->mm_list); |
1299 | spin_unlock(&priv->list_lock); | 1370 | spin_unlock(&priv->list_lock); |
1300 | 1371 | ||
1372 | if (omap_obj->flags & OMAP_BO_MEM_PIN) | ||
1373 | omap_gem_put_paddr_locked(obj); | ||
1374 | |||
1301 | /* this means the object is still pinned.. which really should | 1375 | /* this means the object is still pinned.. which really should |
1302 | * not happen. I think.. | 1376 | * not happen. I think.. |
1303 | */ | 1377 | */ |
@@ -1344,6 +1418,11 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev, | |||
1344 | return NULL; | 1418 | return NULL; |
1345 | } | 1419 | } |
1346 | 1420 | ||
1421 | if (flags & OMAP_BO_MEM_CONTIG) { | ||
1422 | dev_err(dev->dev, "Tiled buffers require TILER memory\n"); | ||
1423 | return NULL; | ||
1424 | } | ||
1425 | |||
1347 | /* | 1426 | /* |
1348 | * Tiled buffers are always shmem paged backed. When they are | 1427 | * Tiled buffers are always shmem paged backed. When they are |
1349 | * scanned out, they are remapped into DMM/TILER. | 1428 | * scanned out, they are remapped into DMM/TILER. |
@@ -1357,7 +1436,8 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev, | |||
1357 | */ | 1436 | */ |
1358 | flags &= ~(OMAP_BO_CACHED|OMAP_BO_WC|OMAP_BO_UNCACHED); | 1437 | flags &= ~(OMAP_BO_CACHED|OMAP_BO_WC|OMAP_BO_UNCACHED); |
1359 | flags |= tiler_get_cpu_cache_flags(); | 1438 | flags |= tiler_get_cpu_cache_flags(); |
1360 | } else if ((flags & OMAP_BO_SCANOUT) && !priv->has_dmm) { | 1439 | } else if ((flags & OMAP_BO_MEM_CONTIG) || |
1440 | ((flags & OMAP_BO_SCANOUT) && !priv->has_dmm)) { | ||
1361 | /* | 1441 | /* |
1362 | * OMAP_BO_SCANOUT hints that the buffer doesn't need to be | 1442 | * OMAP_BO_SCANOUT hints that the buffer doesn't need to be |
1363 | * tiled. However, to lower the pressure on memory allocation, | 1443 | * tiled. However, to lower the pressure on memory allocation, |
@@ -1417,12 +1497,24 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev, | |||
1417 | goto err_release; | 1497 | goto err_release; |
1418 | } | 1498 | } |
1419 | 1499 | ||
1500 | if (flags & OMAP_BO_MEM_PIN) { | ||
1501 | dma_addr_t dummy; | ||
1502 | |||
1503 | ret = omap_gem_get_paddr(obj, &dummy, true); | ||
1504 | if (ret) | ||
1505 | goto err_free_dma; | ||
1506 | } | ||
1507 | |||
1420 | spin_lock(&priv->list_lock); | 1508 | spin_lock(&priv->list_lock); |
1421 | list_add(&omap_obj->mm_list, &priv->obj_list); | 1509 | list_add(&omap_obj->mm_list, &priv->obj_list); |
1422 | spin_unlock(&priv->list_lock); | 1510 | spin_unlock(&priv->list_lock); |
1423 | 1511 | ||
1424 | return obj; | 1512 | return obj; |
1425 | 1513 | ||
1514 | err_free_dma: | ||
1515 | if (flags & OMAP_BO_MEM_DMA_API) | ||
1516 | dma_free_writecombine(dev->dev, size, | ||
1517 | omap_obj->vaddr, omap_obj->paddr); | ||
1426 | err_release: | 1518 | err_release: |
1427 | drm_gem_object_release(obj); | 1519 | drm_gem_object_release(obj); |
1428 | err_free: | 1520 | err_free: |
diff --git a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c index 3da25d54523a..f418a7d07205 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c +++ b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c | |||
@@ -31,43 +31,23 @@ static struct sg_table *omap_gem_map_dma_buf( | |||
31 | { | 31 | { |
32 | struct drm_gem_object *obj = attachment->dmabuf->priv; | 32 | struct drm_gem_object *obj = attachment->dmabuf->priv; |
33 | struct sg_table *sg; | 33 | struct sg_table *sg; |
34 | dma_addr_t paddr; | ||
35 | int ret; | ||
36 | |||
37 | sg = kzalloc(sizeof(*sg), GFP_KERNEL); | ||
38 | if (!sg) | ||
39 | return ERR_PTR(-ENOMEM); | ||
40 | |||
41 | /* camera, etc, need physically contiguous.. but we need a | ||
42 | * better way to know this.. | ||
43 | */ | ||
44 | ret = omap_gem_get_paddr(obj, &paddr, true); | ||
45 | if (ret) | ||
46 | goto out; | ||
47 | 34 | ||
48 | ret = sg_alloc_table(sg, 1, GFP_KERNEL); | 35 | sg = omap_gem_get_sgt(obj); |
49 | if (ret) | 36 | if (IS_ERR(sg)) |
50 | goto out; | 37 | return sg; |
51 | |||
52 | sg_init_table(sg->sgl, 1); | ||
53 | sg_dma_len(sg->sgl) = obj->size; | ||
54 | sg_set_page(sg->sgl, pfn_to_page(PFN_DOWN(paddr)), obj->size, 0); | ||
55 | sg_dma_address(sg->sgl) = paddr; | ||
56 | 38 | ||
57 | /* this should be after _get_paddr() to ensure we have pages attached */ | 39 | /* this should be after _get_paddr() to ensure we have pages attached */ |
58 | omap_gem_dma_sync(obj, dir); | 40 | omap_gem_dma_sync(obj, dir); |
59 | 41 | ||
60 | return sg; | 42 | return sg; |
61 | out: | ||
62 | kfree(sg); | ||
63 | return ERR_PTR(ret); | ||
64 | } | 43 | } |
65 | 44 | ||
66 | static void omap_gem_unmap_dma_buf(struct dma_buf_attachment *attachment, | 45 | static void omap_gem_unmap_dma_buf(struct dma_buf_attachment *attachment, |
67 | struct sg_table *sg, enum dma_data_direction dir) | 46 | struct sg_table *sg, enum dma_data_direction dir) |
68 | { | 47 | { |
69 | struct drm_gem_object *obj = attachment->dmabuf->priv; | 48 | struct drm_gem_object *obj = attachment->dmabuf->priv; |
70 | omap_gem_put_paddr(obj); | 49 | |
50 | omap_gem_put_sgt(obj, sg); | ||
71 | sg_free_table(sg); | 51 | sg_free_table(sg); |
72 | kfree(sg); | 52 | kfree(sg); |
73 | } | 53 | } |
diff --git a/drivers/hwspinlock/Kconfig b/drivers/hwspinlock/Kconfig index 73a401662853..7980d5082197 100644 --- a/drivers/hwspinlock/Kconfig +++ b/drivers/hwspinlock/Kconfig | |||
@@ -8,6 +8,15 @@ config HWSPINLOCK | |||
8 | 8 | ||
9 | menu "Hardware Spinlock drivers" | 9 | menu "Hardware Spinlock drivers" |
10 | 10 | ||
11 | config HWSPINLOCK_USER | ||
12 | tristate "Hardware Spinlock User-Space Interface" | ||
13 | depends on HWSPINLOCK | ||
14 | help | ||
15 | Say y here to have an user-space interface for the hardware spinlock | ||
16 | functionality. | ||
17 | |||
18 | If unsure, say N. | ||
19 | |||
11 | config HWSPINLOCK_OMAP | 20 | config HWSPINLOCK_OMAP |
12 | tristate "OMAP Hardware Spinlock device" | 21 | tristate "OMAP Hardware Spinlock device" |
13 | depends on ARCH_OMAP4 || SOC_OMAP5 || SOC_DRA7XX || SOC_AM33XX || SOC_AM43XX | 22 | depends on ARCH_OMAP4 || SOC_OMAP5 || SOC_DRA7XX || SOC_AM33XX || SOC_AM43XX |
diff --git a/drivers/hwspinlock/Makefile b/drivers/hwspinlock/Makefile index 6b59cb5a4f3a..1407cbad4df0 100644 --- a/drivers/hwspinlock/Makefile +++ b/drivers/hwspinlock/Makefile | |||
@@ -3,6 +3,7 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_HWSPINLOCK) += hwspinlock_core.o | 5 | obj-$(CONFIG_HWSPINLOCK) += hwspinlock_core.o |
6 | obj-$(CONFIG_HWSPINLOCK_USER) += hwspinlock_user.o | ||
6 | obj-$(CONFIG_HWSPINLOCK_OMAP) += omap_hwspinlock.o | 7 | obj-$(CONFIG_HWSPINLOCK_OMAP) += omap_hwspinlock.o |
7 | obj-$(CONFIG_HWSPINLOCK_QCOM) += qcom_hwspinlock.o | 8 | obj-$(CONFIG_HWSPINLOCK_QCOM) += qcom_hwspinlock.o |
8 | obj-$(CONFIG_HWSPINLOCK_SIRF) += sirf_hwspinlock.o | 9 | obj-$(CONFIG_HWSPINLOCK_SIRF) += sirf_hwspinlock.o |
diff --git a/drivers/hwspinlock/hwspinlock_core.c b/drivers/hwspinlock/hwspinlock_core.c index d50c701b19d6..6122b5f1ca60 100644 --- a/drivers/hwspinlock/hwspinlock_core.c +++ b/drivers/hwspinlock/hwspinlock_core.c | |||
@@ -110,6 +110,8 @@ int __hwspin_trylock(struct hwspinlock *hwlock, int mode, unsigned long *flags) | |||
110 | ret = spin_trylock_irqsave(&hwlock->lock, *flags); | 110 | ret = spin_trylock_irqsave(&hwlock->lock, *flags); |
111 | else if (mode == HWLOCK_IRQ) | 111 | else if (mode == HWLOCK_IRQ) |
112 | ret = spin_trylock_irq(&hwlock->lock); | 112 | ret = spin_trylock_irq(&hwlock->lock); |
113 | else if (mode == HWLOCK_MUTEX) | ||
114 | ret = mutex_trylock(&hwlock->mutex); | ||
113 | else | 115 | else |
114 | ret = spin_trylock(&hwlock->lock); | 116 | ret = spin_trylock(&hwlock->lock); |
115 | 117 | ||
@@ -126,6 +128,8 @@ int __hwspin_trylock(struct hwspinlock *hwlock, int mode, unsigned long *flags) | |||
126 | spin_unlock_irqrestore(&hwlock->lock, *flags); | 128 | spin_unlock_irqrestore(&hwlock->lock, *flags); |
127 | else if (mode == HWLOCK_IRQ) | 129 | else if (mode == HWLOCK_IRQ) |
128 | spin_unlock_irq(&hwlock->lock); | 130 | spin_unlock_irq(&hwlock->lock); |
131 | else if (mode == HWLOCK_MUTEX) | ||
132 | mutex_unlock(&hwlock->mutex); | ||
129 | else | 133 | else |
130 | spin_unlock(&hwlock->lock); | 134 | spin_unlock(&hwlock->lock); |
131 | 135 | ||
@@ -253,6 +257,8 @@ void __hwspin_unlock(struct hwspinlock *hwlock, int mode, unsigned long *flags) | |||
253 | spin_unlock_irqrestore(&hwlock->lock, *flags); | 257 | spin_unlock_irqrestore(&hwlock->lock, *flags); |
254 | else if (mode == HWLOCK_IRQ) | 258 | else if (mode == HWLOCK_IRQ) |
255 | spin_unlock_irq(&hwlock->lock); | 259 | spin_unlock_irq(&hwlock->lock); |
260 | else if (mode == HWLOCK_MUTEX) | ||
261 | mutex_unlock(&hwlock->mutex); | ||
256 | else | 262 | else |
257 | spin_unlock(&hwlock->lock); | 263 | spin_unlock(&hwlock->lock); |
258 | } | 264 | } |
@@ -426,6 +432,7 @@ int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev, | |||
426 | hwlock = &bank->lock[i]; | 432 | hwlock = &bank->lock[i]; |
427 | 433 | ||
428 | spin_lock_init(&hwlock->lock); | 434 | spin_lock_init(&hwlock->lock); |
435 | mutex_init(&hwlock->mutex); | ||
429 | hwlock->bank = bank; | 436 | hwlock->bank = bank; |
430 | 437 | ||
431 | ret = hwspin_lock_register_single(hwlock, base_id + i); | 438 | ret = hwspin_lock_register_single(hwlock, base_id + i); |
diff --git a/drivers/hwspinlock/hwspinlock_internal.h b/drivers/hwspinlock/hwspinlock_internal.h index d26f78b8f214..586e64630632 100644 --- a/drivers/hwspinlock/hwspinlock_internal.h +++ b/drivers/hwspinlock/hwspinlock_internal.h | |||
@@ -48,6 +48,7 @@ struct hwspinlock_ops { | |||
48 | struct hwspinlock { | 48 | struct hwspinlock { |
49 | struct hwspinlock_device *bank; | 49 | struct hwspinlock_device *bank; |
50 | spinlock_t lock; | 50 | spinlock_t lock; |
51 | struct mutex mutex; | ||
51 | void *priv; | 52 | void *priv; |
52 | }; | 53 | }; |
53 | 54 | ||
diff --git a/drivers/hwspinlock/hwspinlock_user.c b/drivers/hwspinlock/hwspinlock_user.c new file mode 100644 index 000000000000..cdd8bbdd3b26 --- /dev/null +++ b/drivers/hwspinlock/hwspinlock_user.c | |||
@@ -0,0 +1,231 @@ | |||
1 | /* | ||
2 | * Userspace interface to hardware spinlocks | ||
3 | * | ||
4 | * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms 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 that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/device.h> | ||
19 | #include <linux/hwspinlock.h> | ||
20 | #include <linux/of_device.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/uaccess.h> | ||
23 | #include <linux/fs.h> | ||
24 | #include <uapi/linux/hwspinlock_user.h> | ||
25 | |||
26 | #include <linux/miscdevice.h> | ||
27 | |||
28 | struct hwlock { | ||
29 | struct hwspinlock *hwlock; | ||
30 | struct file *owner; | ||
31 | }; | ||
32 | |||
33 | struct hwspinlock_user { | ||
34 | struct device *dev; | ||
35 | struct mutex mutex; | ||
36 | |||
37 | int num_locks; | ||
38 | struct hwlock locks[0]; | ||
39 | }; | ||
40 | |||
41 | struct hwspinlock_user *user; | ||
42 | |||
43 | static long hwspinlock_user_ioctl(struct file *filp, unsigned int cmd, | ||
44 | unsigned long arg) | ||
45 | { | ||
46 | struct hwspinlock *hwlock = NULL; | ||
47 | union { | ||
48 | struct hwspinlock_user_lock lock; | ||
49 | struct hwspinlock_user_unlock unlock; | ||
50 | } data; | ||
51 | int i, id, ret = 0; | ||
52 | |||
53 | if (copy_from_user(&data, (void __user *)arg, _IOC_SIZE(cmd))) | ||
54 | return -EFAULT; | ||
55 | |||
56 | mutex_lock(&user->mutex); | ||
57 | |||
58 | switch (cmd) { | ||
59 | case HWSPINLOCK_USER_LOCK: | ||
60 | for (i = 0; i < user->num_locks; i++) { | ||
61 | id = hwspin_lock_get_id(user->locks[i].hwlock); | ||
62 | if (id == data.lock.id) { | ||
63 | hwlock = user->locks[i].hwlock; | ||
64 | break; | ||
65 | } | ||
66 | } | ||
67 | |||
68 | if (hwlock) { | ||
69 | ret = hwspin_lock_timeout_can_sleep(hwlock, | ||
70 | data.lock.timeout); | ||
71 | if (!ret) | ||
72 | user->locks[i].owner = filp; | ||
73 | } else { | ||
74 | dev_err(user->dev, "hwspinlock %d is not reserved\n", | ||
75 | data.lock.id); | ||
76 | ret = -EINVAL; | ||
77 | } | ||
78 | break; | ||
79 | |||
80 | case HWSPINLOCK_USER_UNLOCK: | ||
81 | for (i = 0; i < user->num_locks; i++) { | ||
82 | id = hwspin_lock_get_id(user->locks[i].hwlock); | ||
83 | if (id == data.unlock.id) { | ||
84 | hwlock = user->locks[i].hwlock; | ||
85 | break; | ||
86 | } | ||
87 | } | ||
88 | |||
89 | if (hwlock) { | ||
90 | hwspin_unlock_can_sleep(hwlock); | ||
91 | user->locks[i].owner = NULL; | ||
92 | } else { | ||
93 | dev_err(user->dev, "hwspinlock %d is not reserved\n", | ||
94 | data.unlock.id); | ||
95 | ret = -EINVAL; | ||
96 | } | ||
97 | break; | ||
98 | |||
99 | default: | ||
100 | ret = -ENOTTY; | ||
101 | break; | ||
102 | } | ||
103 | |||
104 | mutex_unlock(&user->mutex); | ||
105 | |||
106 | return ret; | ||
107 | } | ||
108 | |||
109 | static int hwspinlock_user_release(struct inode *inode, struct file *filp) | ||
110 | { | ||
111 | int i; | ||
112 | |||
113 | mutex_lock(&user->mutex); | ||
114 | |||
115 | for (i = 0; i < user->num_locks; i++) { | ||
116 | if (user->locks[i].owner == filp) { | ||
117 | dev_warn(user->dev, | ||
118 | "hwspinlock %d is forcefully unlocked\n", | ||
119 | hwspin_lock_get_id(user->locks[i].hwlock)); | ||
120 | hwspin_unlock_can_sleep(user->locks[i].hwlock); | ||
121 | } | ||
122 | } | ||
123 | |||
124 | mutex_unlock(&user->mutex); | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | |||
130 | static const struct file_operations hwspinlock_user_fops = { | ||
131 | .owner = THIS_MODULE, | ||
132 | .unlocked_ioctl = hwspinlock_user_ioctl, | ||
133 | .release = hwspinlock_user_release, | ||
134 | .llseek = noop_llseek, | ||
135 | }; | ||
136 | |||
137 | static struct miscdevice hwspinlock_user_miscdev = { | ||
138 | .minor = MISC_DYNAMIC_MINOR, | ||
139 | .name = "hwspinlock", | ||
140 | .fops = &hwspinlock_user_fops, | ||
141 | }; | ||
142 | |||
143 | static int hwspinlock_user_probe(struct platform_device *pdev) | ||
144 | { | ||
145 | struct device_node *node = pdev->dev.of_node; | ||
146 | struct hwspinlock *hwlock; | ||
147 | int num, id, i; | ||
148 | int ret; | ||
149 | |||
150 | if (!node) | ||
151 | return -ENODEV; | ||
152 | |||
153 | num = of_count_phandle_with_args(node, "hwlocks", "#hwlock-cells"); | ||
154 | |||
155 | user = devm_kzalloc(&pdev->dev, sizeof(struct hwspinlock_user) + | ||
156 | num * sizeof(struct hwlock), GFP_KERNEL); | ||
157 | if (!user) | ||
158 | return -ENOMEM; | ||
159 | |||
160 | user->dev = &pdev->dev; | ||
161 | user->num_locks = num; | ||
162 | mutex_init(&user->mutex); | ||
163 | |||
164 | ret = misc_register(&hwspinlock_user_miscdev); | ||
165 | if (ret) { | ||
166 | dev_err(user->dev, "failed to register miscdev %d\n", ret); | ||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | for (i = 0; i < user->num_locks; i++) { | ||
171 | id = of_hwspin_lock_get_id(node, i); | ||
172 | if (id < 0) { | ||
173 | dev_err(user->dev, "failed to get lock id %d\n", id); | ||
174 | ret = -ENODEV; | ||
175 | goto err; | ||
176 | } | ||
177 | |||
178 | hwlock = hwspin_lock_request_specific(id); | ||
179 | if (IS_ERR_OR_NULL(hwlock)) { | ||
180 | dev_err(user->dev, "failed to request lock %d\n", id); | ||
181 | ret = IS_ERR(hwlock) ? PTR_ERR(hwlock) : -EBUSY; | ||
182 | goto err; | ||
183 | } | ||
184 | |||
185 | user->locks[i].hwlock = hwlock; | ||
186 | } | ||
187 | |||
188 | dev_info(user->dev, "requested %d hwspinlocks\n", i); | ||
189 | |||
190 | platform_set_drvdata(pdev, user); | ||
191 | |||
192 | return 0; | ||
193 | |||
194 | err: | ||
195 | misc_deregister(&hwspinlock_user_miscdev); | ||
196 | for (i--; i >= 0; i--) | ||
197 | hwspin_lock_free(user->locks[i].hwlock); | ||
198 | |||
199 | return ret; | ||
200 | } | ||
201 | |||
202 | static int hwspinlock_user_remove(struct platform_device *pdev) | ||
203 | { | ||
204 | struct hwspinlock_user *user = platform_get_drvdata(pdev); | ||
205 | int i; | ||
206 | |||
207 | misc_deregister(&hwspinlock_user_miscdev); | ||
208 | |||
209 | for (i = 0; i < user->num_locks; i++) | ||
210 | hwspin_lock_free(user->locks[i].hwlock); | ||
211 | |||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | static const struct of_device_id hwspinlock_user_of_match[] = { | ||
216 | { .compatible = "hwspinlock-user", }, | ||
217 | { /* end */ }, | ||
218 | }; | ||
219 | MODULE_DEVICE_TABLE(of, hwspinlock_user_of_match); | ||
220 | |||
221 | static struct platform_driver hwspinlock_user_driver = { | ||
222 | .probe = hwspinlock_user_probe, | ||
223 | .remove = hwspinlock_user_remove, | ||
224 | .driver = { | ||
225 | .name = "hwspinlock_user", | ||
226 | .owner = THIS_MODULE, | ||
227 | .of_match_table = of_match_ptr(hwspinlock_user_of_match), | ||
228 | }, | ||
229 | }; | ||
230 | |||
231 | module_platform_driver(hwspinlock_user_driver); | ||
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 709527cd4c2e..97f1eacdda0e 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -325,6 +325,7 @@ config TOUCHSCREEN_GOODIX | |||
325 | tristate "Goodix I2C touchscreen" | 325 | tristate "Goodix I2C touchscreen" |
326 | depends on I2C | 326 | depends on I2C |
327 | depends on GPIOLIB | 327 | depends on GPIOLIB |
328 | select INPUT_POLLDEV | ||
328 | help | 329 | help |
329 | Say Y here if you have the Goodix touchscreen (such as one | 330 | Say Y here if you have the Goodix touchscreen (such as one |
330 | installed in Onda v975w tablets) connected to your | 331 | installed in Onda v975w tablets) connected to your |
@@ -1107,4 +1108,16 @@ config TOUCHSCREEN_ROHM_BU21023 | |||
1107 | To compile this driver as a module, choose M here: the | 1108 | To compile this driver as a module, choose M here: the |
1108 | module will be called bu21023_ts. | 1109 | module will be called bu21023_ts. |
1109 | 1110 | ||
1111 | config TOUCHSCREEN_LDC3001 | ||
1112 | tristate "LDC3001 ROIC based Touch screen controllers" | ||
1113 | depends on I2C | ||
1114 | help | ||
1115 | Say Y here if you have a LDC3001 plus LGD STM32F103 | ||
1116 | MCU based touchscreen controller. | ||
1117 | |||
1118 | If unsure, say N. | ||
1119 | |||
1120 | To compile this driver as a module, choose M here: the | ||
1121 | module will be called ldc3001_ts. | ||
1122 | |||
1110 | endif | 1123 | endif |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index cbaa6abb08da..595176cb07cf 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
@@ -91,3 +91,4 @@ obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o | |||
91 | obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o | 91 | obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o |
92 | obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o | 92 | obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o |
93 | obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o | 93 | obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o |
94 | obj-$(CONFIG_TOUCHSCREEN_LDC3001) += ldc3001_ts.o | ||
diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index a27f0d7107af..916c9877261f 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/i2c.h> | 22 | #include <linux/i2c.h> |
23 | #include <linux/input.h> | 23 | #include <linux/input.h> |
24 | #include <linux/input/mt.h> | 24 | #include <linux/input/mt.h> |
25 | #include <linux/input-polldev.h> | ||
25 | #include <linux/module.h> | 26 | #include <linux/module.h> |
26 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
27 | #include <linux/irq.h> | 28 | #include <linux/irq.h> |
@@ -34,6 +35,7 @@ | |||
34 | struct goodix_ts_data { | 35 | struct goodix_ts_data { |
35 | struct i2c_client *client; | 36 | struct i2c_client *client; |
36 | struct input_dev *input_dev; | 37 | struct input_dev *input_dev; |
38 | struct input_polled_dev *poll_dev; | ||
37 | int abs_x_max; | 39 | int abs_x_max; |
38 | int abs_y_max; | 40 | int abs_y_max; |
39 | bool swapped_x_y; | 41 | bool swapped_x_y; |
@@ -77,6 +79,8 @@ struct goodix_ts_data { | |||
77 | #define MAX_CONTACTS_LOC 5 | 79 | #define MAX_CONTACTS_LOC 5 |
78 | #define TRIGGER_LOC 6 | 80 | #define TRIGGER_LOC 6 |
79 | 81 | ||
82 | #define TSC_DEFAULT_POLL_PERIOD 30 /* ms */ | ||
83 | |||
80 | static const unsigned long goodix_irq_flags[] = { | 84 | static const unsigned long goodix_irq_flags[] = { |
81 | IRQ_TYPE_EDGE_RISING, | 85 | IRQ_TYPE_EDGE_RISING, |
82 | IRQ_TYPE_EDGE_FALLING, | 86 | IRQ_TYPE_EDGE_FALLING, |
@@ -281,6 +285,20 @@ static void goodix_process_events(struct goodix_ts_data *ts) | |||
281 | input_sync(ts->input_dev); | 285 | input_sync(ts->input_dev); |
282 | } | 286 | } |
283 | 287 | ||
288 | static void _goodix_process_events(struct goodix_ts_data *ts) | ||
289 | { | ||
290 | goodix_process_events(ts); | ||
291 | |||
292 | if (goodix_i2c_write_u8(ts->client, GOODIX_READ_COOR_ADDR, 0) < 0) | ||
293 | dev_err(&ts->client->dev, "I2C write end_cmd error\n"); | ||
294 | |||
295 | } | ||
296 | static void goodix_poll(struct input_polled_dev *poll_dev) | ||
297 | { | ||
298 | struct goodix_ts_data *ts = poll_dev->private; | ||
299 | |||
300 | _goodix_process_events(ts); | ||
301 | } | ||
284 | /** | 302 | /** |
285 | * goodix_ts_irq_handler - The IRQ handler | 303 | * goodix_ts_irq_handler - The IRQ handler |
286 | * | 304 | * |
@@ -291,10 +309,7 @@ static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id) | |||
291 | { | 309 | { |
292 | struct goodix_ts_data *ts = dev_id; | 310 | struct goodix_ts_data *ts = dev_id; |
293 | 311 | ||
294 | goodix_process_events(ts); | 312 | _goodix_process_events(ts); |
295 | |||
296 | if (goodix_i2c_write_u8(ts->client, GOODIX_READ_COOR_ADDR, 0) < 0) | ||
297 | dev_err(&ts->client->dev, "I2C write end_cmd error\n"); | ||
298 | 313 | ||
299 | return IRQ_HANDLED; | 314 | return IRQ_HANDLED; |
300 | } | 315 | } |
@@ -614,6 +629,58 @@ static int goodix_request_input_dev(struct goodix_ts_data *ts) | |||
614 | return 0; | 629 | return 0; |
615 | } | 630 | } |
616 | 631 | ||
632 | static int goodix_request_input_polled_dev(struct goodix_ts_data *ts) | ||
633 | { | ||
634 | int error; | ||
635 | struct input_polled_dev *poll_dev; | ||
636 | |||
637 | dev_err(&ts->client->dev, "Setting up polling.\n"); | ||
638 | poll_dev = input_allocate_polled_device(); | ||
639 | if (!poll_dev) { | ||
640 | dev_err(&ts->client->dev, "Failed to allocate polled input device.\n"); | ||
641 | error = -ENOMEM; | ||
642 | return error; | ||
643 | } | ||
644 | |||
645 | ts->poll_dev = poll_dev; | ||
646 | |||
647 | poll_dev->private = ts; | ||
648 | poll_dev->poll = goodix_poll; | ||
649 | poll_dev->poll_interval = TSC_DEFAULT_POLL_PERIOD; | ||
650 | |||
651 | ts->input_dev = poll_dev->input; | ||
652 | if (!ts->input_dev) { | ||
653 | dev_err(&ts->client->dev, "Failed to allocate input device."); | ||
654 | return -ENOMEM; | ||
655 | } | ||
656 | |||
657 | input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, | ||
658 | 0, ts->abs_x_max, 0, 0); | ||
659 | input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, | ||
660 | 0, ts->abs_y_max, 0, 0); | ||
661 | input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0); | ||
662 | input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); | ||
663 | |||
664 | input_mt_init_slots(ts->input_dev, ts->max_touch_num, | ||
665 | INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); | ||
666 | |||
667 | ts->input_dev->name = "Goodix Capacitive TouchScreen"; | ||
668 | ts->input_dev->phys = "input/ts"; | ||
669 | ts->input_dev->id.bustype = BUS_I2C; | ||
670 | ts->input_dev->id.vendor = 0x0416; | ||
671 | ts->input_dev->id.product = ts->id; | ||
672 | ts->input_dev->id.version = ts->version; | ||
673 | |||
674 | error = input_register_polled_device(poll_dev); | ||
675 | if (error) { | ||
676 | dev_err(&ts->client->dev, | ||
677 | "Failed to register input device: %d", error); | ||
678 | return error; | ||
679 | } | ||
680 | |||
681 | return 0; | ||
682 | } | ||
683 | |||
617 | /** | 684 | /** |
618 | * goodix_configure_dev - Finish device initialization | 685 | * goodix_configure_dev - Finish device initialization |
619 | * | 686 | * |
@@ -637,15 +704,23 @@ static int goodix_configure_dev(struct goodix_ts_data *ts) | |||
637 | 704 | ||
638 | goodix_read_config(ts); | 705 | goodix_read_config(ts); |
639 | 706 | ||
640 | error = goodix_request_input_dev(ts); | 707 | if (ts->client->irq) { |
641 | if (error) | 708 | error = goodix_request_input_dev(ts); |
642 | return error; | 709 | if (error) |
710 | return error; | ||
711 | ts->irq_flags = goodix_irq_flags[ts->int_trigger_type] | | ||
712 | IRQF_ONESHOT; | ||
713 | error = goodix_request_irq(ts); | ||
714 | if (error) { | ||
715 | dev_err(&ts->client->dev, "request IRQ failed: %d\n", | ||
716 | error); | ||
717 | return error; | ||
718 | } | ||
719 | } else { | ||
720 | /* setup polling if IRQ is not defined */ | ||
721 | |||
722 | error = goodix_request_input_polled_dev(ts); | ||
643 | 723 | ||
644 | ts->irq_flags = goodix_irq_flags[ts->int_trigger_type] | IRQF_ONESHOT; | ||
645 | error = goodix_request_irq(ts); | ||
646 | if (error) { | ||
647 | dev_err(&ts->client->dev, "request IRQ failed: %d\n", error); | ||
648 | return error; | ||
649 | } | 724 | } |
650 | 725 | ||
651 | return 0; | 726 | return 0; |
diff --git a/drivers/input/touchscreen/ldc3001_ts.c b/drivers/input/touchscreen/ldc3001_ts.c new file mode 100644 index 000000000000..6cc0798a7e08 --- /dev/null +++ b/drivers/input/touchscreen/ldc3001_ts.c | |||
@@ -0,0 +1,526 @@ | |||
1 | /* | ||
2 | * LDC3001 Touch Screen driver | ||
3 | * | ||
4 | * Copyright (C) 2013-2014 Texas Instruments Incorporated - http://www.ti.com/ | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation version 2. | ||
9 | * | ||
10 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
11 | * kind, whether express or implied; without even the implied warranty | ||
12 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/kthread.h> | ||
20 | #include <linux/firmware.h> | ||
21 | #include <linux/i2c.h> | ||
22 | #include <linux/input/mt.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/gpio.h> | ||
26 | #include <linux/of.h> | ||
27 | #include <linux/of_gpio.h> | ||
28 | #include <linux/of_device.h> | ||
29 | #include <linux/of_irq.h> | ||
30 | #include <linux/regmap.h> | ||
31 | |||
32 | |||
33 | #define TSC_READ_LEN 1 | ||
34 | #define DEFAULT_READ_LEN 2 /* corresponds to the ID bit-field */ | ||
35 | #define TP_READ_SIZE 3 /* co-ordinates size in bytes */ | ||
36 | #define MAX_PAYLOAD_SIZE(mt_points) ((mt_points * TP_READ_SIZE) \ | ||
37 | + DEFAULT_READ_LEN) | ||
38 | |||
39 | /* MACROS to decode data from the i2c messages */ | ||
40 | #define GET_X_POS(msg) (((((msg)[0] >> 4) & 0x0f) << 8) \ | ||
41 | | ((msg)[1])) | ||
42 | |||
43 | #define GET_Y_POS(msg) ((((msg)[0] & 0x0f)) << 8 | ((msg)[2])) | ||
44 | |||
45 | #define GET_INDICES(msg) ((((msg)[0] & 0x00ff) \ | ||
46 | | (((msg)[1]) & 0x30) << 4)) | ||
47 | |||
48 | /* i2c offsets for the tsc */ | ||
49 | #define TOUCH_DATA_ADDR 0xFA | ||
50 | #define TOUCH_DATA_COUNT_ADDR 0xF5 | ||
51 | |||
52 | /* defines a touch */ | ||
53 | struct touch_point { | ||
54 | u8 touch_id; | ||
55 | u8 state; | ||
56 | int x_pos; | ||
57 | int y_pos; | ||
58 | }; | ||
59 | |||
60 | /* platform data for the LGPhilips LDC3001 TSC */ | ||
61 | struct ldc3001_platform_data { | ||
62 | unsigned int x_size; | ||
63 | unsigned int y_size; | ||
64 | unsigned int num_mt_slots; | ||
65 | }; | ||
66 | |||
67 | /* each client has this additional data */ | ||
68 | struct ldc3001_data { | ||
69 | struct i2c_client *client; | ||
70 | struct input_dev *input_dev; | ||
71 | char phys[64]; /* device physical location */ | ||
72 | const struct ldc3001_platform_data *pdata; | ||
73 | unsigned int irq; | ||
74 | u8 *message; | ||
75 | struct touch_point *tps; | ||
76 | u8 cur_index; | ||
77 | u16 tp_fields; | ||
78 | }; | ||
79 | |||
80 | static ssize_t ldc3001_fw_version_show(struct device *dev, | ||
81 | struct device_attribute *attr, char *buf) { | ||
82 | /* FIXME: read TLC to get TS version */ | ||
83 | return scnprintf(buf, PAGE_SIZE, "1.04\n"); | ||
84 | |||
85 | } | ||
86 | static DEVICE_ATTR(fw_version, S_IRUGO, ldc3001_fw_version_show, NULL); | ||
87 | |||
88 | static struct attribute *ldc3001_attrs[] = { | ||
89 | &dev_attr_fw_version.attr, | ||
90 | NULL | ||
91 | }; | ||
92 | |||
93 | static const struct attribute_group ldc3001_attr_group = { | ||
94 | .attrs = ldc3001_attrs, | ||
95 | }; | ||
96 | |||
97 | #ifdef CONFIG_PM_SLEEP | ||
98 | static int ldc3001_i2c_ts_suspend(struct device *dev) | ||
99 | { | ||
100 | dev_dbg(dev, "%s\n", __func__); | ||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static int ldc3001_i2c_ts_resume(struct device *dev) | ||
105 | { | ||
106 | dev_dbg(dev, "%s\n", __func__); | ||
107 | |||
108 | return 0; | ||
109 | } | ||
110 | #endif | ||
111 | |||
112 | static SIMPLE_DEV_PM_OPS(ldc3001_dev_pm_ops, | ||
113 | ldc3001_i2c_ts_suspend, ldc3001_i2c_ts_resume); | ||
114 | |||
115 | |||
116 | #ifdef DEBUG | ||
117 | static void dump_touch_data(u8 *message, int len) | ||
118 | { | ||
119 | |||
120 | print_hex_dump(KERN_ERR, " \t", DUMP_PREFIX_NONE, 16, 1, | ||
121 | message, len, false); | ||
122 | } | ||
123 | |||
124 | static u16 get_touch_fields(struct ldc3001_data *data) | ||
125 | { | ||
126 | u8 *message = data->message; | ||
127 | |||
128 | pr_info("Bit field is %u\n", GET_INDICES(message)); | ||
129 | return GET_INDICES(message); | ||
130 | } | ||
131 | |||
132 | /* | ||
133 | * index - index to the read message | ||
134 | * touch_idx - touch_idx tracking id | ||
135 | */ | ||
136 | |||
137 | static void get_tpos(struct ldc3001_data *data, u8 index, u8 touch_idx) | ||
138 | { | ||
139 | u16 x, y; | ||
140 | u8 *message = &data->message[index*TP_READ_SIZE + DEFAULT_READ_LEN]; | ||
141 | |||
142 | data->tps[index].x_pos = GET_X_POS(msg); | ||
143 | data->tps[index].y_pos = GET_Y_POS(msg); | ||
144 | data->tps[index].touch_id = touch_idx; | ||
145 | |||
146 | pr_info("x %x\n", data->tps[index].x_pos); | ||
147 | pr_info("y %x\n", data->tps[index].y_pos); | ||
148 | |||
149 | } | ||
150 | |||
151 | static int ldc3001_write_reg(struct i2c_client *client, u16 reg, u16 len, | ||
152 | const void *val) | ||
153 | { | ||
154 | u8 *buf; | ||
155 | size_t count; | ||
156 | int ret; | ||
157 | |||
158 | count = len + 2; | ||
159 | buf = kmalloc(count, GFP_KERNEL); | ||
160 | if (!buf) | ||
161 | return -ENOMEM; | ||
162 | |||
163 | /* pack the 16 bit reg value to byte data */ | ||
164 | buf[0] = reg & 0xff; | ||
165 | buf[1] = (reg >> 8) & 0xff; | ||
166 | memcpy(&buf[2], val, len); | ||
167 | |||
168 | ret = i2c_master_send(client, buf, count); | ||
169 | if (ret == count) { | ||
170 | ret = 0; | ||
171 | } else { | ||
172 | if (ret >= 0) | ||
173 | ret = -EIO; | ||
174 | dev_err(&client->dev, "%s: i2c send failed (%d)\n", | ||
175 | __func__, ret); | ||
176 | } | ||
177 | |||
178 | kfree(buf); | ||
179 | return ret; | ||
180 | } | ||
181 | #endif | ||
182 | |||
183 | static int ldc3001_read_reg(struct i2c_client *client, | ||
184 | u16 reg, u16 len, void *val) | ||
185 | { | ||
186 | struct i2c_msg xfer[2]; | ||
187 | u8 buf[2]; | ||
188 | int ret; | ||
189 | |||
190 | /* pack the 16 bit reg value to byte data */ | ||
191 | buf[0] = reg & 0xff; | ||
192 | buf[1] = (reg >> 8) & 0xff; | ||
193 | |||
194 | /* Write register */ | ||
195 | xfer[0].addr = client->addr; | ||
196 | xfer[0].flags = 0; | ||
197 | xfer[0].len = 2; | ||
198 | xfer[0].buf = buf; | ||
199 | |||
200 | /* Read data */ | ||
201 | xfer[1].addr = client->addr; | ||
202 | xfer[1].flags = I2C_M_RD; | ||
203 | xfer[1].len = len; | ||
204 | xfer[1].buf = val; | ||
205 | |||
206 | ret = i2c_transfer(client->adapter, xfer, 2); | ||
207 | if (ret == 2) { | ||
208 | ret = 0; | ||
209 | } else { | ||
210 | if (ret >= 0) | ||
211 | ret = -EIO; | ||
212 | dev_err(&client->dev, "%s: i2c transfer failed (%d)\n", | ||
213 | __func__, ret); | ||
214 | } | ||
215 | |||
216 | return ret; | ||
217 | } | ||
218 | |||
219 | |||
220 | static int ldc3001_ts_read_data(struct ldc3001_data *data, int len) | ||
221 | { | ||
222 | int error; | ||
223 | struct i2c_client *client = data->client; | ||
224 | |||
225 | error = ldc3001_read_reg(client, TOUCH_DATA_ADDR, len, data->message); | ||
226 | if (error) | ||
227 | dev_err(&client->dev, "i2c_read failed %x\n", error); | ||
228 | |||
229 | return error; | ||
230 | } | ||
231 | |||
232 | static int ldc3001_ts_read_len(struct ldc3001_data *data) | ||
233 | { | ||
234 | int error; | ||
235 | u8 len = 0; | ||
236 | |||
237 | struct i2c_client *client = data->client; | ||
238 | |||
239 | error = ldc3001_read_reg(client, TOUCH_DATA_COUNT_ADDR, TSC_READ_LEN, | ||
240 | &len); | ||
241 | if (error) | ||
242 | dev_err(&client->dev, "i2c_read len failed %x\n", error); | ||
243 | |||
244 | return len; | ||
245 | } | ||
246 | |||
247 | |||
248 | |||
249 | static void ldc3001_input_touchevent(struct ldc3001_data *data) | ||
250 | { | ||
251 | u16 touch_index = 0; | ||
252 | u8 i, msg_index = 0; | ||
253 | int num_mt_slots = data->pdata->num_mt_slots; | ||
254 | struct input_dev *input_dev = data->input_dev; | ||
255 | u8 *message = data->message; | ||
256 | |||
257 | /* get valid touch ids */ | ||
258 | touch_index = GET_INDICES(message); | ||
259 | |||
260 | /* loop through all tps to process changes */ | ||
261 | for (i = 0; i < num_mt_slots; i++) { | ||
262 | |||
263 | /* tracking id has a touch event */ | ||
264 | if (touch_index & (1 << i)) { | ||
265 | message = | ||
266 | &data->message[msg_index * TP_READ_SIZE + DEFAULT_READ_LEN]; | ||
267 | |||
268 | /* decode the x and y co-ordinates */ | ||
269 | data->tps[i].x_pos = GET_X_POS(message); | ||
270 | data->tps[i].y_pos = GET_Y_POS(message); | ||
271 | |||
272 | /* update state and move to the next message */ | ||
273 | data->tps[i].state = 1; | ||
274 | msg_index++; | ||
275 | |||
276 | /* report the touch event */ | ||
277 | input_mt_slot(input_dev, i); | ||
278 | input_mt_report_slot_state(input_dev, | ||
279 | MT_TOOL_FINGER, data->tps[i].state); | ||
280 | input_report_abs(input_dev, ABS_MT_POSITION_X, | ||
281 | data->tps[i].x_pos); | ||
282 | input_report_abs(input_dev, ABS_MT_POSITION_Y, | ||
283 | data->tps[i].y_pos); | ||
284 | |||
285 | } else if (data->tps[i].state == 1) { | ||
286 | /* this is a pen release event */ | ||
287 | data->tps[i].state = 0; | ||
288 | input_mt_slot(input_dev, i); | ||
289 | input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, | ||
290 | data->tps[i].state); | ||
291 | } | ||
292 | } | ||
293 | |||
294 | /* send sync event */ | ||
295 | input_mt_report_pointer_emulation(data->input_dev, false); | ||
296 | input_sync(input_dev); | ||
297 | } | ||
298 | |||
299 | |||
300 | static irqreturn_t ldc3001_ts_interrupt(int irq, void *dev_id) | ||
301 | { | ||
302 | struct ldc3001_data *data = (struct ldc3001_data *)dev_id; | ||
303 | int read_len; | ||
304 | |||
305 | /* FIXME: need to figure out why this is required */ | ||
306 | disable_irq_nosync(irq); | ||
307 | |||
308 | read_len = ldc3001_ts_read_len(data); | ||
309 | |||
310 | /* reset touchid fields */ | ||
311 | data->message[0] = 0x0; | ||
312 | data->message[1] = 0x0; | ||
313 | |||
314 | if (read_len > DEFAULT_READ_LEN) | ||
315 | /* fill the message array with data read from tsc */ | ||
316 | ldc3001_ts_read_data(data, read_len); | ||
317 | |||
318 | ldc3001_input_touchevent(data); | ||
319 | enable_irq(irq); | ||
320 | |||
321 | return IRQ_HANDLED; | ||
322 | } | ||
323 | |||
324 | int ldc3001_of_populate(struct i2c_client *client, | ||
325 | struct ldc3001_platform_data *pdata) | ||
326 | { | ||
327 | struct device_node *node = client->dev.of_node; | ||
328 | unsigned int val; | ||
329 | int ret = -EINVAL; | ||
330 | |||
331 | ret = of_property_read_u32(node, "res-x", &val); | ||
332 | if (ret) | ||
333 | goto error; | ||
334 | pdata->x_size = val; | ||
335 | |||
336 | ret = of_property_read_u32(node, "res-y", &val); | ||
337 | if (ret) | ||
338 | goto error; | ||
339 | |||
340 | pdata->y_size = val; | ||
341 | |||
342 | ret = of_property_read_u32(node, "max-touch-points", &val); | ||
343 | if (ret) | ||
344 | goto error; | ||
345 | |||
346 | pdata->num_mt_slots = val; | ||
347 | |||
348 | error: | ||
349 | return ret; | ||
350 | } | ||
351 | |||
352 | static const struct of_device_id ldc3001_dt_ids[] = { | ||
353 | { .compatible = "lgphilips,ldc3001"}, | ||
354 | { /* sentinel */ } | ||
355 | }; | ||
356 | |||
357 | static int ldc3001_probe(struct i2c_client *client, | ||
358 | const struct i2c_device_id *idev_id) | ||
359 | { | ||
360 | struct device_node *node = client->dev.of_node; | ||
361 | struct ldc3001_platform_data *pdata; | ||
362 | struct ldc3001_data *data; | ||
363 | struct input_dev *input_dev; | ||
364 | const struct of_device_id *match; | ||
365 | int error; | ||
366 | |||
367 | match = of_match_device(of_match_ptr(ldc3001_dt_ids), &client->dev); | ||
368 | if (match) { | ||
369 | pdata = devm_kzalloc(&client->dev, | ||
370 | sizeof(struct ldc3001_platform_data), GFP_KERNEL); | ||
371 | if (!pdata) | ||
372 | return -ENOMEM; | ||
373 | |||
374 | /* get dt values to populate platform data */ | ||
375 | error = ldc3001_of_populate(client, pdata); | ||
376 | if (error) | ||
377 | return -EINVAL; | ||
378 | |||
379 | } else { | ||
380 | pdata = client->dev.platform_data; | ||
381 | if (!pdata) { | ||
382 | dev_err(&client->dev, "platform data not populated\n"); | ||
383 | return -EINVAL; | ||
384 | } | ||
385 | } | ||
386 | |||
387 | data = devm_kzalloc(&client->dev, | ||
388 | sizeof(struct ldc3001_data), GFP_KERNEL); | ||
389 | |||
390 | if (!data) { | ||
391 | error = -ENOMEM; | ||
392 | goto err_exit; | ||
393 | } | ||
394 | |||
395 | data->tps = devm_kzalloc(&client->dev, | ||
396 | sizeof(struct touch_point) * pdata->num_mt_slots, GFP_KERNEL); | ||
397 | |||
398 | if (!data->tps) { | ||
399 | error = -ENOMEM; | ||
400 | goto err_exit; | ||
401 | } | ||
402 | |||
403 | data->message = devm_kzalloc(&client->dev, | ||
404 | (sizeof(u8) * MAX_PAYLOAD_SIZE(pdata->num_mt_slots)), | ||
405 | GFP_KERNEL); | ||
406 | if (!data->message) { | ||
407 | error = -ENOMEM; | ||
408 | goto err_exit; | ||
409 | } | ||
410 | |||
411 | input_dev = devm_input_allocate_device(&client->dev); | ||
412 | |||
413 | if (!input_dev) { | ||
414 | error = -ENOMEM; | ||
415 | goto err_exit; | ||
416 | } | ||
417 | |||
418 | input_dev->name = "LDC 3001 TouchScreen Controller"; | ||
419 | |||
420 | snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0", | ||
421 | client->adapter->nr, client->addr); | ||
422 | |||
423 | input_dev->phys = data->phys; | ||
424 | |||
425 | input_dev->dev.parent = &client->dev; | ||
426 | data->client = client; | ||
427 | data->input_dev = input_dev; | ||
428 | data->pdata = pdata; | ||
429 | |||
430 | input_set_drvdata(input_dev, data); | ||
431 | i2c_set_clientdata(client, data); | ||
432 | |||
433 | /*TODO: Need to poke the tlc chip to read revision of the TSC chip */ | ||
434 | |||
435 | __set_bit(EV_ABS, input_dev->evbit); | ||
436 | __set_bit(EV_KEY, input_dev->evbit); | ||
437 | __set_bit(BTN_TOUCH, input_dev->keybit); | ||
438 | |||
439 | /* For single touch */ | ||
440 | input_set_abs_params(input_dev, ABS_X, | ||
441 | 0, pdata->x_size, 0, 0); | ||
442 | input_set_abs_params(input_dev, ABS_Y, | ||
443 | 0, pdata->y_size, 0, 0); | ||
444 | |||
445 | /* For multi touch */ | ||
446 | error = input_mt_init_slots(input_dev, pdata->num_mt_slots, 0); | ||
447 | |||
448 | if (error) | ||
449 | goto err_exit; | ||
450 | |||
451 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, | ||
452 | 0, pdata->x_size, 0, 0); | ||
453 | input_set_abs_params(input_dev, ABS_MT_POSITION_Y, | ||
454 | 0, pdata->y_size, 0, 0); | ||
455 | |||
456 | data->irq = irq_of_parse_and_map(node, 0); | ||
457 | if (data->irq) { | ||
458 | error = devm_request_threaded_irq(&client->dev, data->irq, | ||
459 | NULL, ldc3001_ts_interrupt, | ||
460 | IRQF_ONESHOT | IRQF_TRIGGER_HIGH, | ||
461 | dev_name(&client->dev), data); | ||
462 | |||
463 | if (error) { | ||
464 | dev_err(&client->dev, "failed to register interrupt\n"); | ||
465 | goto cleanup_exit; | ||
466 | } | ||
467 | } else { | ||
468 | dev_err(&client->dev, | ||
469 | "failed registering irq = %d\n", data->irq); | ||
470 | error = -EINVAL; | ||
471 | goto cleanup_exit; | ||
472 | } | ||
473 | |||
474 | error = input_register_device(input_dev); | ||
475 | if (error) | ||
476 | input_free_device(input_dev); | ||
477 | else { | ||
478 | error = sysfs_create_group(&client->dev.kobj, | ||
479 | &ldc3001_attr_group); | ||
480 | return error; | ||
481 | } | ||
482 | |||
483 | cleanup_exit: | ||
484 | input_mt_destroy_slots(input_dev); | ||
485 | err_exit: | ||
486 | return error; | ||
487 | } | ||
488 | |||
489 | static int ldc3001_remove(struct i2c_client *client) | ||
490 | { | ||
491 | |||
492 | struct ldc3001_data *data = | ||
493 | (struct ldc3001_data *)i2c_get_clientdata(client); | ||
494 | struct input_dev *input_dev = data->input_dev; | ||
495 | |||
496 | sysfs_remove_group(&client->dev.kobj, &ldc3001_attr_group); | ||
497 | input_unregister_device(input_dev); | ||
498 | |||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | static const struct i2c_device_id ldc3001_i2c_id[] = { | ||
503 | {"ldc3001", 0}, | ||
504 | { } | ||
505 | }; | ||
506 | |||
507 | MODULE_DEVICE_TABLE(i2c, ldc3001_i2c_id); | ||
508 | |||
509 | static struct i2c_driver ldc3001_i2c_driver = { | ||
510 | .driver = { | ||
511 | .owner = THIS_MODULE, | ||
512 | .name = "ldc3001", | ||
513 | .pm = &ldc3001_dev_pm_ops, | ||
514 | .of_match_table = ldc3001_dt_ids, | ||
515 | }, | ||
516 | .probe = ldc3001_probe, | ||
517 | .remove = ldc3001_remove, | ||
518 | .id_table = ldc3001_i2c_id, | ||
519 | }; | ||
520 | |||
521 | module_i2c_driver(ldc3001_i2c_driver); | ||
522 | |||
523 | MODULE_AUTHOR("Subramaniam Chanderashekarapuram <subramaniam.ca@ti.com>"); | ||
524 | MODULE_DESCRIPTION("LDC3001 I2C Touchscreen driver"); | ||
525 | MODULE_LICENSE("GPL"); | ||
526 | MODULE_ALIAS("i2c:ldc3001"); | ||
diff --git a/drivers/iommu/omap-iommu-debug.c b/drivers/iommu/omap-iommu-debug.c index 505548aafeff..78cec6fd5e00 100644 --- a/drivers/iommu/omap-iommu-debug.c +++ b/drivers/iommu/omap-iommu-debug.c | |||
@@ -197,7 +197,10 @@ static void dump_ioptable(struct seq_file *s) | |||
197 | continue; | 197 | continue; |
198 | } | 198 | } |
199 | 199 | ||
200 | iopte = iopte_offset(iopgd, 0); | 200 | if (obj->late_attach) |
201 | iopte = iopte_offset_lateattach(obj, iopgd, 0); | ||
202 | else | ||
203 | iopte = iopte_offset(iopgd, 0); | ||
201 | for (j = 0; j < PTRS_PER_IOPTE; j++, iopte++) { | 204 | for (j = 0; j < PTRS_PER_IOPTE; j++, iopte++) { |
202 | if (!*iopte) | 205 | if (!*iopte) |
203 | continue; | 206 | continue; |
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index 4cb603e5ba70..f6ec55ab0233 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c | |||
@@ -183,7 +183,7 @@ static int omap2_iommu_enable(struct omap_iommu *obj) | |||
183 | if (!obj->iopgd || !IS_ALIGNED((u32)obj->iopgd, SZ_16K)) | 183 | if (!obj->iopgd || !IS_ALIGNED((u32)obj->iopgd, SZ_16K)) |
184 | return -EINVAL; | 184 | return -EINVAL; |
185 | 185 | ||
186 | pa = virt_to_phys(obj->iopgd); | 186 | pa = obj->iopgd_pa; |
187 | if (!IS_ALIGNED(pa, SZ_16K)) | 187 | if (!IS_ALIGNED(pa, SZ_16K)) |
188 | return -EINVAL; | 188 | return -EINVAL; |
189 | 189 | ||
@@ -218,6 +218,15 @@ static int iommu_enable(struct omap_iommu *obj) | |||
218 | { | 218 | { |
219 | int ret; | 219 | int ret; |
220 | 220 | ||
221 | /* | ||
222 | * now that the threat of idling has passed, decrement the | ||
223 | * device usage count to balance the increment done in probe, | ||
224 | * the pm runtime device usage count will be managed normally | ||
225 | * from here on | ||
226 | */ | ||
227 | if (obj->late_attach) | ||
228 | pm_runtime_put_noidle(obj->dev); | ||
229 | |||
221 | ret = pm_runtime_get_sync(obj->dev); | 230 | ret = pm_runtime_get_sync(obj->dev); |
222 | if (ret < 0) | 231 | if (ret < 0) |
223 | pm_runtime_put_noidle(obj->dev); | 232 | pm_runtime_put_noidle(obj->dev); |
@@ -530,7 +539,10 @@ static u32 *iopte_alloc(struct omap_iommu *obj, u32 *iopgd, u32 da) | |||
530 | } | 539 | } |
531 | 540 | ||
532 | pte_ready: | 541 | pte_ready: |
533 | iopte = iopte_offset(iopgd, da); | 542 | if (obj->late_attach) |
543 | iopte = iopte_offset_lateattach(obj, iopgd, da); | ||
544 | else | ||
545 | iopte = iopte_offset(iopgd, da); | ||
534 | 546 | ||
535 | dev_vdbg(obj->dev, | 547 | dev_vdbg(obj->dev, |
536 | "%s: da:%08x pgd:%p *pgd:%08x pte:%p *pte:%08x\n", | 548 | "%s: da:%08x pgd:%p *pgd:%08x pte:%p *pte:%08x\n", |
@@ -682,8 +694,12 @@ iopgtable_lookup_entry(struct omap_iommu *obj, u32 da, u32 **ppgd, u32 **ppte) | |||
682 | if (!*iopgd) | 694 | if (!*iopgd) |
683 | goto out; | 695 | goto out; |
684 | 696 | ||
685 | if (iopgd_is_table(*iopgd)) | 697 | if (iopgd_is_table(*iopgd)) { |
686 | iopte = iopte_offset(iopgd, da); | 698 | if (obj->late_attach) |
699 | iopte = iopte_offset_lateattach(obj, iopgd, da); | ||
700 | else | ||
701 | iopte = iopte_offset(iopgd, da); | ||
702 | } | ||
687 | out: | 703 | out: |
688 | *ppgd = iopgd; | 704 | *ppgd = iopgd; |
689 | *ppte = iopte; | 705 | *ppte = iopte; |
@@ -700,13 +716,23 @@ static size_t iopgtable_clear_entry_core(struct omap_iommu *obj, u32 da) | |||
700 | 716 | ||
701 | if (iopgd_is_table(*iopgd)) { | 717 | if (iopgd_is_table(*iopgd)) { |
702 | int i; | 718 | int i; |
703 | u32 *iopte = iopte_offset(iopgd, da); | 719 | u32 *iopte; |
720 | |||
721 | if (obj->late_attach) | ||
722 | iopte = iopte_offset_lateattach(obj, iopgd, da); | ||
723 | else | ||
724 | iopte = iopte_offset(iopgd, da); | ||
704 | 725 | ||
705 | bytes = IOPTE_SIZE; | 726 | bytes = IOPTE_SIZE; |
706 | if (*iopte & IOPTE_LARGE) { | 727 | if (*iopte & IOPTE_LARGE) { |
707 | nent *= 16; | 728 | nent *= 16; |
708 | /* rewind to the 1st entry */ | 729 | /* rewind to the 1st entry */ |
709 | iopte = iopte_offset(iopgd, (da & IOLARGE_MASK)); | 730 | if (obj->late_attach) |
731 | iopte = iopte_offset_lateattach(obj, iopgd, | ||
732 | (da & IOLARGE_MASK)); | ||
733 | else | ||
734 | iopte = iopte_offset(iopgd, | ||
735 | (da & IOLARGE_MASK)); | ||
710 | } | 736 | } |
711 | bytes *= nent; | 737 | bytes *= nent; |
712 | memset(iopte, 0, nent * sizeof(*iopte)); | 738 | memset(iopte, 0, nent * sizeof(*iopte)); |
@@ -715,7 +741,11 @@ static size_t iopgtable_clear_entry_core(struct omap_iommu *obj, u32 da) | |||
715 | /* | 741 | /* |
716 | * do table walk to check if this table is necessary or not | 742 | * do table walk to check if this table is necessary or not |
717 | */ | 743 | */ |
718 | iopte = iopte_offset(iopgd, 0); | 744 | if (obj->late_attach) |
745 | iopte = iopte_offset_lateattach(obj, iopgd, 0); | ||
746 | else | ||
747 | iopte = iopte_offset(iopgd, 0); | ||
748 | |||
719 | for (i = 0; i < PTRS_PER_IOPTE; i++) | 749 | for (i = 0; i < PTRS_PER_IOPTE; i++) |
720 | if (iopte[i]) | 750 | if (iopte[i]) |
721 | goto out; | 751 | goto out; |
@@ -772,8 +802,13 @@ static void iopgtable_clear_entry_all(struct omap_iommu *obj) | |||
772 | if (!*iopgd) | 802 | if (!*iopgd) |
773 | continue; | 803 | continue; |
774 | 804 | ||
775 | if (iopgd_is_table(*iopgd)) | 805 | if (iopgd_is_table(*iopgd)) { |
776 | iopte_free(iopte_offset(iopgd, 0)); | 806 | if (obj->late_attach) |
807 | iopte_free(iopte_offset_lateattach(obj, | ||
808 | iopgd, 0)); | ||
809 | else | ||
810 | iopte_free(iopte_offset(iopgd, 0)); | ||
811 | } | ||
777 | 812 | ||
778 | *iopgd = 0; | 813 | *iopgd = 0; |
779 | flush_iopgd_range(iopgd, iopgd + 1); | 814 | flush_iopgd_range(iopgd, iopgd + 1); |
@@ -816,7 +851,10 @@ static irqreturn_t iommu_fault_handler(int irq, void *data) | |||
816 | return IRQ_NONE; | 851 | return IRQ_NONE; |
817 | } | 852 | } |
818 | 853 | ||
819 | iopte = iopte_offset(iopgd, da); | 854 | if (obj->late_attach) |
855 | iopte = iopte_offset_lateattach(obj, iopgd, da); | ||
856 | else | ||
857 | iopte = iopte_offset(iopgd, da); | ||
820 | 858 | ||
821 | dev_err(obj->dev, "%s: errs:0x%08x da:0x%08x pgd:0x%p *pgd:0x%08x pte:0x%p *pte:0x%08x\n", | 859 | dev_err(obj->dev, "%s: errs:0x%08x da:0x%08x pgd:0x%p *pgd:0x%08x pte:0x%p *pte:0x%08x\n", |
822 | obj->name, errs, da, iopgd, *iopgd, iopte, *iopte); | 860 | obj->name, errs, da, iopgd, *iopgd, iopte, *iopte); |
@@ -844,6 +882,7 @@ static struct omap_iommu *omap_iommu_attach(const char *name, u32 *iopgd) | |||
844 | int err; | 882 | int err; |
845 | struct device *dev; | 883 | struct device *dev; |
846 | struct omap_iommu *obj; | 884 | struct omap_iommu *obj; |
885 | u32 iopgd_pa; | ||
847 | 886 | ||
848 | dev = driver_find_device(&omap_iommu_driver.driver, NULL, (void *)name, | 887 | dev = driver_find_device(&omap_iommu_driver.driver, NULL, (void *)name, |
849 | device_match_by_alias); | 888 | device_match_by_alias); |
@@ -852,13 +891,25 @@ static struct omap_iommu *omap_iommu_attach(const char *name, u32 *iopgd) | |||
852 | 891 | ||
853 | obj = to_iommu(dev); | 892 | obj = to_iommu(dev); |
854 | 893 | ||
894 | if (obj->late_attach) { | ||
895 | iopgd_pa = iommu_read_reg(obj, MMU_TTB); | ||
896 | iopgd = devm_ioremap(obj->dev, iopgd_pa, | ||
897 | 2 * IOPGD_TABLE_SIZE); | ||
898 | if (!iopgd) | ||
899 | return ERR_PTR(-ENOMEM); | ||
900 | } else { | ||
901 | iopgd_pa = virt_to_phys(iopgd); | ||
902 | } | ||
903 | |||
855 | spin_lock(&obj->iommu_lock); | 904 | spin_lock(&obj->iommu_lock); |
856 | 905 | ||
906 | obj->iopgd_pa = iopgd_pa; | ||
857 | obj->iopgd = iopgd; | 907 | obj->iopgd = iopgd; |
858 | err = iommu_enable(obj); | 908 | err = iommu_enable(obj); |
859 | if (err) | 909 | if (err) |
860 | goto err_enable; | 910 | goto err_enable; |
861 | flush_iotlb_all(obj); | 911 | if (!obj->late_attach) |
912 | flush_iotlb_all(obj); | ||
862 | 913 | ||
863 | spin_unlock(&obj->iommu_lock); | 914 | spin_unlock(&obj->iommu_lock); |
864 | 915 | ||
@@ -879,10 +930,16 @@ static void omap_iommu_detach(struct omap_iommu *obj) | |||
879 | if (!obj || IS_ERR(obj)) | 930 | if (!obj || IS_ERR(obj)) |
880 | return; | 931 | return; |
881 | 932 | ||
933 | if (obj->late_attach && obj->iopgd) | ||
934 | iounmap(obj->iopgd); | ||
935 | |||
882 | spin_lock(&obj->iommu_lock); | 936 | spin_lock(&obj->iommu_lock); |
883 | 937 | ||
938 | obj->iopgd_pa = 0; | ||
884 | obj->iopgd = NULL; | 939 | obj->iopgd = NULL; |
885 | iommu_disable(obj); | 940 | iommu_disable(obj); |
941 | obj->late_attach = 0; | ||
942 | obj->late_attach_dma_pool = 0; | ||
886 | 943 | ||
887 | spin_unlock(&obj->iommu_lock); | 944 | spin_unlock(&obj->iommu_lock); |
888 | 945 | ||
@@ -1056,7 +1113,10 @@ static int omap_iommu_runtime_resume(struct device *dev) | |||
1056 | } | 1113 | } |
1057 | } | 1114 | } |
1058 | 1115 | ||
1059 | if (pdata && pdata->deassert_reset) { | 1116 | /* do not deassert reset only during initial boot for late attach */ |
1117 | if ((!obj->late_attach || obj->domain) && | ||
1118 | pdata && pdata->deassert_reset) { | ||
1119 | |||
1060 | ret = pdata->deassert_reset(pdev, pdata->reset_name); | 1120 | ret = pdata->deassert_reset(pdev, pdata->reset_name); |
1061 | if (ret) { | 1121 | if (ret) { |
1062 | dev_err(dev, "deassert_reset failed: %d\n", ret); | 1122 | dev_err(dev, "deassert_reset failed: %d\n", ret); |
@@ -1140,6 +1200,7 @@ static int omap_iommu_probe(struct platform_device *pdev) | |||
1140 | struct resource *res; | 1200 | struct resource *res; |
1141 | struct iommu_platform_data *pdata = dev_get_platdata(&pdev->dev); | 1201 | struct iommu_platform_data *pdata = dev_get_platdata(&pdev->dev); |
1142 | struct device_node *of = pdev->dev.of_node; | 1202 | struct device_node *of = pdev->dev.of_node; |
1203 | struct property *prop; | ||
1143 | 1204 | ||
1144 | obj = devm_kzalloc(&pdev->dev, sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL); | 1205 | obj = devm_kzalloc(&pdev->dev, sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL); |
1145 | if (!obj) | 1206 | if (!obj) |
@@ -1165,6 +1226,35 @@ static int omap_iommu_probe(struct platform_device *pdev) | |||
1165 | return -EINVAL; | 1226 | return -EINVAL; |
1166 | if (of_find_property(of, "ti,iommu-bus-err-back", NULL)) | 1227 | if (of_find_property(of, "ti,iommu-bus-err-back", NULL)) |
1167 | obj->has_bus_err_back = MMU_GP_REG_BUS_ERR_BACK_EN; | 1228 | obj->has_bus_err_back = MMU_GP_REG_BUS_ERR_BACK_EN; |
1229 | |||
1230 | prop = of_find_property(of, "ti,late-attach", NULL); | ||
1231 | if (prop) { | ||
1232 | obj->late_attach = 1; | ||
1233 | /* | ||
1234 | * Clear the late attach property in device tree for | ||
1235 | * subsequent probes. | ||
1236 | */ | ||
1237 | err = of_remove_property(of, prop); | ||
1238 | if (err < 0) | ||
1239 | dev_err(&pdev->dev, "Unable to remove late-attach property\n"); | ||
1240 | |||
1241 | /* | ||
1242 | * Check to see if using a DMA pool (instead of CMA | ||
1243 | * pool) | ||
1244 | */ | ||
1245 | prop = of_find_property(of, "ti,late-attach-dma-pool", | ||
1246 | NULL); | ||
1247 | if (prop) { | ||
1248 | obj->late_attach_dma_pool = 1; | ||
1249 | /* | ||
1250 | * Clear the late attach property in device | ||
1251 | * tree for subsequent probes. | ||
1252 | */ | ||
1253 | err = of_remove_property(of, prop); | ||
1254 | if (err < 0) | ||
1255 | dev_err(&pdev->dev, "Unable to remove late-attach-dma-pool property\n"); | ||
1256 | } | ||
1257 | } | ||
1168 | } else { | 1258 | } else { |
1169 | obj->nr_tlb_entries = pdata->nr_tlb_entries; | 1259 | obj->nr_tlb_entries = pdata->nr_tlb_entries; |
1170 | obj->name = pdata->name; | 1260 | obj->name = pdata->name; |
@@ -1201,6 +1291,15 @@ static int omap_iommu_probe(struct platform_device *pdev) | |||
1201 | platform_set_drvdata(pdev, obj); | 1291 | platform_set_drvdata(pdev, obj); |
1202 | 1292 | ||
1203 | pm_runtime_irq_safe(obj->dev); | 1293 | pm_runtime_irq_safe(obj->dev); |
1294 | |||
1295 | /* | ||
1296 | * increment the device usage count so that runtime_suspend is not | ||
1297 | * invoked immediately after the probe (due to the ti,no-idle-on-init) | ||
1298 | * and before any remoteproc has attached to the iommu | ||
1299 | */ | ||
1300 | if (obj->late_attach) | ||
1301 | pm_runtime_get_noresume(obj->dev); | ||
1302 | |||
1204 | pm_runtime_enable(obj->dev); | 1303 | pm_runtime_enable(obj->dev); |
1205 | 1304 | ||
1206 | omap_iommu_debugfs_add(obj); | 1305 | omap_iommu_debugfs_add(obj); |
@@ -1372,6 +1471,11 @@ static int omap_iommu_attach_init(struct device *dev, | |||
1372 | 1471 | ||
1373 | iommu = odomain->iommus; | 1472 | iommu = odomain->iommus; |
1374 | for (i = 0; i < odomain->num_iommus; i++, iommu++) { | 1473 | for (i = 0; i < odomain->num_iommus; i++, iommu++) { |
1474 | /* | ||
1475 | * Not necessary for late attach. The page table would be setup | ||
1476 | * by the boot loader. Leaving the below code in place it does | ||
1477 | * not have any side effects during late attach. | ||
1478 | */ | ||
1375 | iommu->pgtable = kzalloc(IOPGD_TABLE_SIZE, GFP_ATOMIC); | 1479 | iommu->pgtable = kzalloc(IOPGD_TABLE_SIZE, GFP_ATOMIC); |
1376 | if (!iommu->pgtable) | 1480 | if (!iommu->pgtable) |
1377 | return -ENOMEM; | 1481 | return -ENOMEM; |
@@ -1496,7 +1600,8 @@ static void _omap_iommu_detach_dev(struct omap_iommu_domain *omap_domain, | |||
1496 | arch_data += (omap_domain->num_iommus - 1); | 1600 | arch_data += (omap_domain->num_iommus - 1); |
1497 | for (i = 0; i < omap_domain->num_iommus; i++, iommu--, arch_data--) { | 1601 | for (i = 0; i < omap_domain->num_iommus; i++, iommu--, arch_data--) { |
1498 | oiommu = iommu->iommu_dev; | 1602 | oiommu = iommu->iommu_dev; |
1499 | iopgtable_clear_entry_all(oiommu); | 1603 | if (!oiommu->late_attach) |
1604 | iopgtable_clear_entry_all(oiommu); | ||
1500 | 1605 | ||
1501 | omap_iommu_detach(oiommu); | 1606 | omap_iommu_detach(oiommu); |
1502 | iommu->iommu_dev = NULL; | 1607 | iommu->iommu_dev = NULL; |
diff --git a/drivers/iommu/omap-iommu.h b/drivers/iommu/omap-iommu.h index 257aab294218..a0faab6c249c 100644 --- a/drivers/iommu/omap-iommu.h +++ b/drivers/iommu/omap-iommu.h | |||
@@ -42,6 +42,7 @@ struct omap_iommu { | |||
42 | * but share it globally for each iommu. | 42 | * but share it globally for each iommu. |
43 | */ | 43 | */ |
44 | u32 *iopgd; | 44 | u32 *iopgd; |
45 | u32 iopgd_pa; | ||
45 | spinlock_t page_table_lock; /* protect iopgd */ | 46 | spinlock_t page_table_lock; /* protect iopgd */ |
46 | 47 | ||
47 | int nr_tlb_entries; | 48 | int nr_tlb_entries; |
@@ -55,6 +56,8 @@ struct omap_iommu { | |||
55 | u32 id; | 56 | u32 id; |
56 | 57 | ||
57 | u8 pwrst; | 58 | u8 pwrst; |
59 | u32 late_attach; | ||
60 | u32 late_attach_dma_pool; | ||
58 | }; | 61 | }; |
59 | 62 | ||
60 | struct cr_regs { | 63 | struct cr_regs { |
diff --git a/drivers/iommu/omap-iopgtable.h b/drivers/iommu/omap-iopgtable.h index 01a315227bf0..9a6a6d228765 100644 --- a/drivers/iommu/omap-iopgtable.h +++ b/drivers/iommu/omap-iopgtable.h | |||
@@ -99,4 +99,12 @@ static inline phys_addr_t omap_iommu_translate(u32 d, u32 va, u32 mask) | |||
99 | #define iopte_index(da) (((da) >> IOPTE_SHIFT) & (PTRS_PER_IOPTE - 1)) | 99 | #define iopte_index(da) (((da) >> IOPTE_SHIFT) & (PTRS_PER_IOPTE - 1)) |
100 | #define iopte_offset(iopgd, da) (iopgd_page_vaddr(iopgd) + iopte_index(da)) | 100 | #define iopte_offset(iopgd, da) (iopgd_page_vaddr(iopgd) + iopte_index(da)) |
101 | 101 | ||
102 | /* For late attach */ | ||
103 | #define iopgd_page_vaddr_lateattach(obj, iopgd) \ | ||
104 | ((u32 *)((u32 *)obj->iopgd) + \ | ||
105 | ((u32 *)iopgd_page_paddr(iopgd) - (u32 *)obj->iopgd_pa)) | ||
106 | |||
107 | /* to find an entry in the second-level page table for late attach mode*/ | ||
108 | #define iopte_offset_lateattach(obj, iopgd, da) \ | ||
109 | (iopgd_page_vaddr_lateattach(obj, iopgd) + iopte_index(da)) | ||
102 | #endif /* _OMAP_IOPGTABLE_H */ | 110 | #endif /* _OMAP_IOPGTABLE_H */ |
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 9aa2f6aa79ad..1cb286a0afb0 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig | |||
@@ -317,6 +317,17 @@ config VIDEO_TVP5150 | |||
317 | To compile this driver as a module, choose M here: the | 317 | To compile this driver as a module, choose M here: the |
318 | module will be called tvp5150. | 318 | module will be called tvp5150. |
319 | 319 | ||
320 | config VIDEO_TVP5158 | ||
321 | tristate "Analog video decoder TVP5158 support NTSC/PAL" | ||
322 | depends on I2C && VIDEO_V4L2 | ||
323 | depends on MEDIA_CAMERA_SUPPORT | ||
324 | ---help--- | ||
325 | This is a Video4Linux2 subdevice driver for the TVP5158 | ||
326 | NTSC/PAL video decoder. | ||
327 | |||
328 | To compile this driver as a module, choose M here: the | ||
329 | module will be called tvp5158. | ||
330 | |||
320 | config VIDEO_TVP7002 | 331 | config VIDEO_TVP7002 |
321 | tristate "Texas Instruments TVP7002 video decoder" | 332 | tristate "Texas Instruments TVP7002 video decoder" |
322 | depends on VIDEO_V4L2 && I2C | 333 | depends on VIDEO_V4L2 && I2C |
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index 74f4e962bef3..03b25c0d0cbe 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile | |||
@@ -39,6 +39,7 @@ obj-$(CONFIG_VIDEO_THS7303) += ths7303.o | |||
39 | obj-$(CONFIG_VIDEO_THS8200) += ths8200.o | 39 | obj-$(CONFIG_VIDEO_THS8200) += ths8200.o |
40 | obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o | 40 | obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o |
41 | obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o | 41 | obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o |
42 | obj-$(CONFIG_VIDEO_TVP5158) += tvp5158.o | ||
42 | obj-$(CONFIG_VIDEO_TVP7002) += tvp7002.o | 43 | obj-$(CONFIG_VIDEO_TVP7002) += tvp7002.o |
43 | obj-$(CONFIG_VIDEO_TW2804) += tw2804.o | 44 | obj-$(CONFIG_VIDEO_TW2804) += tw2804.o |
44 | obj-$(CONFIG_VIDEO_TW9903) += tw9903.o | 45 | obj-$(CONFIG_VIDEO_TW9903) += tw9903.o |
diff --git a/drivers/media/i2c/tvp5158.c b/drivers/media/i2c/tvp5158.c new file mode 100644 index 000000000000..314062f86199 --- /dev/null +++ b/drivers/media/i2c/tvp5158.c | |||
@@ -0,0 +1,771 @@ | |||
1 | /* | ||
2 | * TI TVP5158 V4L2 subdevice driver | ||
3 | * | ||
4 | * Copyright (C) 2016 Texas Instruments, Inc. | ||
5 | * Sathishkumar S <sathish.omap@gmail.com> | ||
6 | * Nikhil Devshatwar, <nikhil.nd@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 | |||
14 | #include <linux/delay.h> | ||
15 | #include <linux/i2c.h> | ||
16 | #include <linux/gpio.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/regulator/consumer.h> | ||
20 | #include <linux/regmap.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/v4l2-mediabus.h> | ||
23 | #include <linux/videodev2.h> | ||
24 | |||
25 | #include <media/soc_camera.h> | ||
26 | #include <media/v4l2-async.h> | ||
27 | #include <media/v4l2-common.h> | ||
28 | #include <media/v4l2-ctrls.h> | ||
29 | |||
30 | #include <linux/pm_runtime.h> | ||
31 | |||
32 | #include <linux/of_gpio.h> | ||
33 | #include <linux/of_device.h> | ||
34 | |||
35 | /* Debug functions */ | ||
36 | static bool debug; | ||
37 | module_param(debug, bool, 0644); | ||
38 | MODULE_PARM_DESC(debug, "Debug level (0-2)"); | ||
39 | |||
40 | /* VBUS Register Address (24-bit), VBUS Register value (8-bit) */ | ||
41 | struct vbus_addr_value { | ||
42 | unsigned int addr; | ||
43 | unsigned char val; | ||
44 | }; | ||
45 | |||
46 | struct vbus_addr_value vbus_addr_value_set[] = { | ||
47 | {0x00403E50, 0x40}, | ||
48 | {0x00403E51, 0x00}, | ||
49 | {0x00403E52, 0x40}, | ||
50 | {0x00403E53, 0x00}, | ||
51 | {0x00403E54, 0x44}, | ||
52 | {0x00403E55, 0x23}, | ||
53 | {0x00403E56, 0x38}, | ||
54 | {0x00403E57, 0x10}, | ||
55 | {0x00403E58, 0x53}, | ||
56 | {0x00403E59, 0x23}, | ||
57 | {0x00403E5A, 0x02}, | ||
58 | {0x00403E5B, 0x00}, | ||
59 | {0x00403E5C, 0x20}, | ||
60 | {0x00403E5D, 0x00}, | ||
61 | {0x00403E5E, 0x04}, | ||
62 | {0x00403E5F, 0x04}, | ||
63 | {0x00403E60, 0x04}, | ||
64 | {0x00403E61, 0x04}, | ||
65 | {0x00403E62, 0x10}, | ||
66 | {0x00403E63, 0xF8}, | ||
67 | {0x00403E64, 0x30}, | ||
68 | {0x00403E65, 0x20}, | ||
69 | {0x00403E66, 0x30}, | ||
70 | {0x00403E67, 0x3F}, | ||
71 | {0x00403E68, 0x3F}, | ||
72 | {0x00403E69, 0x3F}, | ||
73 | {0x00403E6A, 0x0C}, | ||
74 | {0x00403E6B, 0x0C}, | ||
75 | {0x00403E6C, 0x80}, | ||
76 | {0x00403E6D, 0x80}, | ||
77 | {0x00403E6E, 0x08}, | ||
78 | {0x00403E6F, 0x08}, | ||
79 | {0x00403E70, 0x08}, | ||
80 | {0x00403E71, 0x30}, | ||
81 | {0x00403E72, 0x08}, | ||
82 | {0x00403E73, 0x04}, | ||
83 | {0x00403E74, 0x00}, | ||
84 | {0x00403E75, 0x10}, | ||
85 | {0x00403E76, 0x00}, | ||
86 | {0x00403E77, 0x00}, | ||
87 | {0x00403E78, 0x38}, | ||
88 | {0x00403E79, 0x00}, | ||
89 | {0x00403E7A, 0x55}, | ||
90 | {0x00403E7B, 0x03}, | ||
91 | {0x00403E7C, 0x03}, | ||
92 | {0x00403E7D, 0x00}, | ||
93 | {0x00403E7E, 0x03}, | ||
94 | {0x00403E7F, 0x00}, | ||
95 | {0x00403E80, 0x30}, | ||
96 | {0x00403E81, 0x30}, | ||
97 | {0x00403E82, 0x18}, | ||
98 | {0x00403E83, 0x0C}, | ||
99 | {0x00403E95, 0x00}, | ||
100 | {0x00403E96, 0x00}, | ||
101 | {0x00403E9B, 0x3F}, | ||
102 | {0x00403EA2, 0x0C}, | ||
103 | {0x00403EA3, 0x10}, | ||
104 | {0x00403EA6, 0x0C}, | ||
105 | {0x00403EA7, 0x10}, | ||
106 | {0x00403EA8, 0x44}, | ||
107 | {0x00403EA9, 0x00}, | ||
108 | }; | ||
109 | static bool vbus_prog = 1; | ||
110 | static int | ||
111 | tvp5158_of_probe(struct i2c_client *client, struct device_node *node); | ||
112 | static int | ||
113 | tvp5158_init_gpios(struct i2c_client *client); | ||
114 | static int | ||
115 | tvp5158_set_default(struct i2c_client *client, unsigned char core); | ||
116 | static enum tvp5158_std | ||
117 | tvp5158_get_video_std(struct i2c_client *client, unsigned char core); | ||
118 | static void | ||
119 | tvp5158_start_streaming(struct i2c_client *client, unsigned char core); | ||
120 | static int | ||
121 | tvp5158_set_int_regs(struct i2c_client *client, struct vbus_addr_value *reg, | ||
122 | int cnt); | ||
123 | |||
124 | #define REG_STAUS_1 0x00 | ||
125 | #define REG_STAUS_2 0x01 | ||
126 | #define REG_VID_STAND 0x0C | ||
127 | #define REG_CHIPID_MSB 0x08 | ||
128 | #define REG_CHIPID_LSB 0x09 | ||
129 | #define REG_AVD_CTRL_1 0xB0 | ||
130 | #define REG_AVD_CTRL_2 0xB1 | ||
131 | #define REG_OFM_CTRL 0xB2 | ||
132 | #define REG_DEC_RD_EN 0xFF | ||
133 | #define REG_DEC_WR_EN 0xFE | ||
134 | #define REG_VBUS_1 0xE8 | ||
135 | #define REG_VBUS_2 0xE9 | ||
136 | #define REG_VBUS_3 0xEA | ||
137 | #define REG_VBUS_DATA 0xE0 | ||
138 | |||
139 | #define TVP_CORE_ALL 0x0F | ||
140 | #define TVP_DECODER_1 (1<<0) | ||
141 | /* Non interleaved */ | ||
142 | #define TVP_INTERLEAVE_MODE_NON (0<<6) | ||
143 | #define TVP_INTERLEAVE_MODE_PIX (1<<6) | ||
144 | #define TVP_INTERLEAVE_MODE_LINE (2<<6) | ||
145 | /* Number of time multiplexed channels = 0 */ | ||
146 | #define TVP_CH_MUX_NUMBER (2<<4) | ||
147 | /* ITU BT 656 8 bit */ | ||
148 | #define TVP_OUTPUT_TYPE (0<<3) | ||
149 | /* Single stage */ | ||
150 | #define TVP_VCS_ID (0<<2) | ||
151 | /* D1 */ | ||
152 | #define TVP_VID_RES (0<<0) | ||
153 | |||
154 | #define TVP_ENABLE_DITHERING (1<<4) | ||
155 | #define TVP_VID_DET_SAVEAV_EN (1<<0) | ||
156 | |||
157 | #define TVP_VIDEO_PORT_ENABLE (1<<0) | ||
158 | #define TVP_OUT_CLK_P_EN (1<<2) | ||
159 | #define TVP_FIELD_RATE (1<<5) | ||
160 | #define TVP_SIGNAL_PRESENT (1<<7) | ||
161 | #define TVP_VIDEO_STANDARD_MASK (0x07) | ||
162 | |||
163 | /* Number of pixels and number of lines per frame for different standards */ | ||
164 | #define NTSC_NUM_ACTIVE_PIXELS (720) | ||
165 | #define NTSC_NUM_ACTIVE_LINES (480) | ||
166 | #define PAL_NUM_ACTIVE_PIXELS (720) | ||
167 | #define PAL_NUM_ACTIVE_LINES (576) | ||
168 | |||
169 | #define MAX_NUM_GPIOS 3 | ||
170 | |||
171 | struct tvp5158_color_format { | ||
172 | u32 code; | ||
173 | enum v4l2_colorspace colorspace; | ||
174 | }; | ||
175 | |||
176 | static const struct tvp5158_color_format tvp5158_cfmts[] = { | ||
177 | { | ||
178 | .code = MEDIA_BUS_FMT_UYVY8_2X8, | ||
179 | .colorspace = V4L2_COLORSPACE_SMPTE170M, | ||
180 | }, | ||
181 | }; | ||
182 | |||
183 | /* enum tvp5158_std - enum for supported standards */ | ||
184 | enum tvp5158_std { | ||
185 | STD_NTSC_MJ = 0, | ||
186 | STD_PAL_BDGHIN, | ||
187 | STD_INVALID | ||
188 | }; | ||
189 | |||
190 | /** | ||
191 | * struct tvp5158_std_info - Structure to store standard information | ||
192 | * @width: Line width in pixels | ||
193 | * @height:Number of active lines | ||
194 | * @standard: v4l2 standard structure information | ||
195 | */ | ||
196 | struct tvp5158_std_info { | ||
197 | unsigned long width; | ||
198 | unsigned long height; | ||
199 | struct v4l2_standard standard; | ||
200 | }; | ||
201 | |||
202 | enum tvp5158_signal_present { | ||
203 | TVP5158_SIGNAL_DEAD = 0, | ||
204 | TVP5158_SIGNAL_PRESENT | ||
205 | }; | ||
206 | struct tvp5158_priv { | ||
207 | struct v4l2_subdev subdev; | ||
208 | struct v4l2_mbus_framefmt format; | ||
209 | enum tvp5158_std current_std; | ||
210 | |||
211 | struct gpio mux_gpios[MAX_NUM_GPIOS]; | ||
212 | int num_gpios; | ||
213 | }; | ||
214 | |||
215 | static const struct tvp5158_std_info std_list[] = { | ||
216 | [STD_NTSC_MJ] = { | ||
217 | .width = NTSC_NUM_ACTIVE_PIXELS, | ||
218 | .height = NTSC_NUM_ACTIVE_LINES, | ||
219 | .standard = { | ||
220 | .index = 0, | ||
221 | .id = V4L2_STD_NTSC, | ||
222 | .name = "NTSC", | ||
223 | .frameperiod = {1001, 30000}, | ||
224 | .framelines = 525 | ||
225 | }, | ||
226 | }, | ||
227 | |||
228 | [STD_PAL_BDGHIN] = { | ||
229 | .width = PAL_NUM_ACTIVE_PIXELS, | ||
230 | .height = PAL_NUM_ACTIVE_LINES, | ||
231 | .standard = { | ||
232 | .index = 1, | ||
233 | .id = V4L2_STD_PAL, | ||
234 | .name = "PAL", | ||
235 | .frameperiod = {1001, 25000}, | ||
236 | .framelines = 625 | ||
237 | }, | ||
238 | }, | ||
239 | }; | ||
240 | |||
241 | static struct tvp5158_priv *to_tvp5158(const struct i2c_client *client) | ||
242 | { | ||
243 | return container_of(i2c_get_clientdata(client), struct tvp5158_priv, | ||
244 | subdev); | ||
245 | } | ||
246 | |||
247 | |||
248 | static int tvp5158_read(struct i2c_client *client, unsigned char addr) | ||
249 | { | ||
250 | unsigned char buffer[1]; | ||
251 | int rc; | ||
252 | |||
253 | buffer[0] = addr; | ||
254 | |||
255 | rc = i2c_master_send(client, buffer, 1); | ||
256 | if (rc < 0) { | ||
257 | dev_err(&client->dev, "i2c i/o error: rc == %d (should be 1)\n" | ||
258 | , rc); | ||
259 | return rc; | ||
260 | } | ||
261 | |||
262 | rc = i2c_master_recv(client, buffer, 1); | ||
263 | if (rc < 0) { | ||
264 | dev_err(&client->dev, "i2c i/o error: rc == %d (should be 1)\n" | ||
265 | , rc); | ||
266 | return rc; | ||
267 | } | ||
268 | |||
269 | return buffer[0]; | ||
270 | } | ||
271 | static inline void tvp5158_write(struct i2c_client *client, unsigned char addr, | ||
272 | unsigned char value) | ||
273 | { | ||
274 | unsigned char buffer[2]; | ||
275 | int rc; | ||
276 | |||
277 | buffer[0] = addr; | ||
278 | buffer[1] = value; | ||
279 | rc = i2c_master_send(client, buffer, 2); | ||
280 | if (rc != 2) | ||
281 | dev_err(&client->dev, "i2c i/o error: rc == %d (should be 2)\n" | ||
282 | , rc); | ||
283 | } | ||
284 | |||
285 | /** | ||
286 | * tvp5158_s_stream() - V4L2 decoder i/f handler for s_stream | ||
287 | * @sd: pointer to standard V4L2 sub-device structure | ||
288 | * @enable: streaming enable or disable | ||
289 | * | ||
290 | * Sets streaming to enable or disable. | ||
291 | */ | ||
292 | static int tvp5158_s_stream(struct v4l2_subdev *sd, int enable) | ||
293 | { | ||
294 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
295 | |||
296 | tvp5158_init_gpios(client); | ||
297 | |||
298 | if (enable) { | ||
299 | if (vbus_prog == 1) | ||
300 | /* VBUS address value setting */ | ||
301 | tvp5158_set_int_regs(client, vbus_addr_value_set, | ||
302 | ARRAY_SIZE(vbus_addr_value_set)); | ||
303 | tvp5158_start_streaming(client, TVP_CORE_ALL); | ||
304 | } else { | ||
305 | tvp5158_write(client, REG_OFM_CTRL, 0x0); | ||
306 | } | ||
307 | |||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | /** | ||
312 | * tvp5158_querystd() - V4L2 decoder interface handler for querystd | ||
313 | * @sd: pointer to standard V4L2 sub-device structure | ||
314 | * @std_id: standard V4L2 std_id ioctl enum | ||
315 | * | ||
316 | * Returns the current standard detected by TVP5146/47. If no active input is | ||
317 | * detected then *std_id is set to 0 and the function returns 0. | ||
318 | */ | ||
319 | static int tvp5158_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id) | ||
320 | { | ||
321 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
322 | struct tvp5158_priv *priv = to_tvp5158(client); | ||
323 | |||
324 | if (std_id == NULL) | ||
325 | return -EINVAL; | ||
326 | *std_id = V4L2_STD_UNKNOWN; | ||
327 | |||
328 | tvp5158_get_video_std(client, TVP_CORE_ALL); | ||
329 | if (priv->current_std == STD_INVALID) | ||
330 | return -ENODEV; | ||
331 | *std_id = std_list[priv->current_std].standard.id; | ||
332 | |||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | /** | ||
337 | * tvp5158_g_parm() - V4L2 decoder interface handler for g_parm | ||
338 | * @sd: pointer to standard V4L2 sub-device structure | ||
339 | * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure | ||
340 | * | ||
341 | * Returns the decoder's video CAPTURE parameters. | ||
342 | */ | ||
343 | static int tvp5158_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) | ||
344 | { | ||
345 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
346 | struct tvp5158_priv *priv = to_tvp5158(client); | ||
347 | struct v4l2_captureparm *cparm; | ||
348 | enum tvp5158_std current_std; | ||
349 | |||
350 | if (parms == NULL || parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
351 | return -EINVAL; | ||
352 | |||
353 | tvp5158_get_video_std(client, TVP_CORE_ALL); | ||
354 | if (priv->current_std == STD_INVALID) | ||
355 | return -ENODEV; | ||
356 | |||
357 | /* get the current standard */ | ||
358 | current_std = priv->current_std; | ||
359 | cparm = &parms->parm.capture; | ||
360 | cparm->capability = V4L2_CAP_TIMEPERFRAME; | ||
361 | cparm->timeperframe = | ||
362 | std_list[current_std].standard.frameperiod; | ||
363 | |||
364 | return 0; | ||
365 | } | ||
366 | |||
367 | /** | ||
368 | * tvp5158_s_parm() - V4L2 decoder interface handler for s_parm | ||
369 | * @sd: pointer to standard V4L2 sub-device structure | ||
370 | * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure | ||
371 | * | ||
372 | * Configures the decoder to use the input parameters, if possible. If | ||
373 | * not possible, returns the appropriate error code. | ||
374 | */ | ||
375 | static int tvp5158_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) | ||
376 | { | ||
377 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
378 | struct tvp5158_priv *priv = to_tvp5158(client); | ||
379 | struct v4l2_fract *timeperframe; | ||
380 | enum tvp5158_std current_std; | ||
381 | |||
382 | if (parms == NULL || parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
383 | return -EINVAL; | ||
384 | |||
385 | timeperframe = &parms->parm.capture.timeperframe; | ||
386 | |||
387 | /* get the current standard */ | ||
388 | current_std = priv->current_std; | ||
389 | if (current_std == STD_INVALID) | ||
390 | return -ENODEV; | ||
391 | |||
392 | *timeperframe = | ||
393 | std_list[current_std].standard.frameperiod; | ||
394 | |||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | static int tvp5158_get_fmt(struct v4l2_subdev *sd, | ||
399 | struct v4l2_subdev_pad_config *cfg, | ||
400 | struct v4l2_subdev_format *fmt) | ||
401 | { | ||
402 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
403 | struct tvp5158_priv *priv = to_tvp5158(client); | ||
404 | struct v4l2_mbus_framefmt *mf; | ||
405 | enum tvp5158_std current_std; | ||
406 | |||
407 | tvp5158_get_video_std(client, TVP_CORE_ALL); | ||
408 | current_std = priv->current_std; | ||
409 | if (current_std == STD_INVALID) | ||
410 | return -EINVAL; | ||
411 | |||
412 | switch (fmt->which) { | ||
413 | case V4L2_SUBDEV_FORMAT_TRY: | ||
414 | mf = v4l2_subdev_get_try_format(sd, cfg, 0); | ||
415 | break; | ||
416 | case V4L2_SUBDEV_FORMAT_ACTIVE: | ||
417 | mf = &priv->format; | ||
418 | break; | ||
419 | default: | ||
420 | return -EINVAL; | ||
421 | } | ||
422 | |||
423 | mf->width = std_list[current_std].width; | ||
424 | mf->height = std_list[current_std].height / 2; | ||
425 | fmt->format = *mf; | ||
426 | |||
427 | return 0; | ||
428 | } | ||
429 | |||
430 | static int tvp5158_set_fmt(struct v4l2_subdev *sd, | ||
431 | struct v4l2_subdev_pad_config *cfg, | ||
432 | struct v4l2_subdev_format *fmt) | ||
433 | |||
434 | { | ||
435 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
436 | struct tvp5158_priv *priv = to_tvp5158(client); | ||
437 | int ret; | ||
438 | |||
439 | if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { | ||
440 | |||
441 | ret = tvp5158_get_fmt(sd, cfg, fmt); | ||
442 | if (ret) | ||
443 | return ret; | ||
444 | |||
445 | priv->format = fmt->format; | ||
446 | } | ||
447 | |||
448 | return 0; | ||
449 | } | ||
450 | |||
451 | static int tvp5158_enum_mbus_code(struct v4l2_subdev *sd, | ||
452 | struct v4l2_subdev_pad_config *cfg, | ||
453 | struct v4l2_subdev_mbus_code_enum *code) | ||
454 | { | ||
455 | if (code->index >= ARRAY_SIZE(tvp5158_cfmts)) | ||
456 | return -EINVAL; | ||
457 | |||
458 | code->code = tvp5158_cfmts[code->index].code; | ||
459 | |||
460 | return 0; | ||
461 | } | ||
462 | |||
463 | static int tvp5158_enum_frame_size(struct v4l2_subdev *sd, | ||
464 | struct v4l2_subdev_pad_config *cfg, | ||
465 | struct v4l2_subdev_frame_size_enum *fse) | ||
466 | { | ||
467 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
468 | struct tvp5158_priv *priv = to_tvp5158(client); | ||
469 | enum tvp5158_std std; | ||
470 | |||
471 | if (fse->index >= 1) | ||
472 | return -EINVAL; | ||
473 | if (priv->current_std == STD_INVALID) | ||
474 | tvp5158_get_video_std(client, TVP_CORE_ALL); | ||
475 | if (priv->current_std == STD_INVALID) | ||
476 | return -ENODEV; | ||
477 | |||
478 | std = priv->current_std; | ||
479 | fse->code = priv->format.code; | ||
480 | |||
481 | fse->max_width = fse->min_width = std_list[std].width; | ||
482 | fse->max_height = fse->min_height = std_list[std].height; | ||
483 | |||
484 | return 0; | ||
485 | } | ||
486 | |||
487 | static int tvp5158_enum_frame_interval(struct v4l2_subdev *sd, | ||
488 | struct v4l2_subdev_pad_config *cfg, | ||
489 | struct v4l2_subdev_frame_interval_enum *fie) | ||
490 | { | ||
491 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
492 | struct tvp5158_priv *priv = to_tvp5158(client); | ||
493 | enum tvp5158_std current_std; | ||
494 | struct v4l2_fract *timeperframe; | ||
495 | |||
496 | /* Each standard has one frame interval, so return | ||
497 | * EINVAL if more are requested | ||
498 | */ | ||
499 | if (fie->index != 0) | ||
500 | return -EINVAL; | ||
501 | |||
502 | /* Get the current standard */ | ||
503 | current_std = priv->current_std; | ||
504 | |||
505 | /* Check if current standard is invalid */ | ||
506 | if (current_std == STD_INVALID) | ||
507 | return -EINVAL; | ||
508 | |||
509 | timeperframe = &fie->interval; | ||
510 | *timeperframe = | ||
511 | std_list[current_std].standard.frameperiod; | ||
512 | |||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | |||
517 | static int tvp5158_of_probe(struct i2c_client *client, | ||
518 | struct device_node *node) | ||
519 | { | ||
520 | struct tvp5158_priv *priv = to_tvp5158(client); | ||
521 | struct gpio *gpios = &priv->mux_gpios[0]; | ||
522 | unsigned int flags; | ||
523 | int i, gpio; | ||
524 | |||
525 | /* Iterate over all the gpios in the device tree | ||
526 | * ENOENT is returned when trying to access last + 1 gpio | ||
527 | */ | ||
528 | for (i = 0; i < MAX_NUM_GPIOS; i++) { | ||
529 | |||
530 | gpio = of_get_named_gpio_flags(node, "mux-gpios", i, &flags); | ||
531 | if (gpio_is_valid(gpio)) { | ||
532 | gpios[i].gpio = gpio; | ||
533 | gpios[i].flags = (flags & OF_GPIO_ACTIVE_LOW) ? | ||
534 | GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH; | ||
535 | gpios[i].label = client->name; | ||
536 | } else if (gpio == -ENOENT) { | ||
537 | break; | ||
538 | } else { | ||
539 | return gpio; | ||
540 | } | ||
541 | } | ||
542 | priv->num_gpios = i; | ||
543 | return 0; | ||
544 | } | ||
545 | |||
546 | static int tvp5158_init_gpios(struct i2c_client *client) | ||
547 | { | ||
548 | struct tvp5158_priv *priv = to_tvp5158(client); | ||
549 | int ret = 0; | ||
550 | |||
551 | ret = gpio_request_array(priv->mux_gpios, priv->num_gpios); | ||
552 | if (ret) | ||
553 | goto done; | ||
554 | gpio_free_array(priv->mux_gpios, priv->num_gpios); | ||
555 | |||
556 | done: | ||
557 | return ret; | ||
558 | } | ||
559 | |||
560 | static struct v4l2_subdev_video_ops tvp5158_video_ops = { | ||
561 | .querystd = tvp5158_querystd, | ||
562 | .g_parm = tvp5158_g_parm, | ||
563 | .s_parm = tvp5158_s_parm, | ||
564 | .s_stream = tvp5158_s_stream, | ||
565 | }; | ||
566 | |||
567 | static struct v4l2_subdev_pad_ops tvp5158_pad_ops = { | ||
568 | .enum_mbus_code = tvp5158_enum_mbus_code, | ||
569 | .enum_frame_size = tvp5158_enum_frame_size, | ||
570 | .enum_frame_interval = tvp5158_enum_frame_interval, | ||
571 | .get_fmt = tvp5158_get_fmt, | ||
572 | .set_fmt = tvp5158_set_fmt, | ||
573 | }; | ||
574 | |||
575 | static struct v4l2_subdev_ops tvp5158_subdev_ops = { | ||
576 | .video = &tvp5158_video_ops, | ||
577 | .pad = &tvp5158_pad_ops, | ||
578 | }; | ||
579 | |||
580 | static const struct i2c_device_id tvp5158_id[] = { | ||
581 | { "ti,tvp5158", 0 }, | ||
582 | { } | ||
583 | }; | ||
584 | MODULE_DEVICE_TABLE(i2c, tvp5158_id); | ||
585 | |||
586 | static const struct of_device_id tvp5158_dt_id[] = { | ||
587 | { | ||
588 | .compatible = "ti,tvp5158", .data = "tvp5158" | ||
589 | }, | ||
590 | { | ||
591 | } | ||
592 | }; | ||
593 | |||
594 | static int tvp5158_set_int_regs(struct i2c_client *client, | ||
595 | struct vbus_addr_value *reg, int cnt) | ||
596 | { | ||
597 | int i = 0; | ||
598 | /* Core Write enable*/ | ||
599 | tvp5158_write(client, REG_DEC_WR_EN, TVP_CORE_ALL); | ||
600 | for (i = 0; i < cnt; i++) { | ||
601 | tvp5158_write(client, REG_VBUS_1, ((reg[i].addr >> 0) & 0xFF)); | ||
602 | tvp5158_write(client, REG_VBUS_2, ((reg[i].addr >> 8) & 0xFF)); | ||
603 | tvp5158_write(client, REG_VBUS_3, ((reg[i].addr >> 16) & 0xFF)); | ||
604 | tvp5158_write(client, REG_VBUS_DATA, reg[i].val); | ||
605 | } | ||
606 | vbus_prog = 0; | ||
607 | return 0; | ||
608 | } | ||
609 | |||
610 | static int | ||
611 | tvp5158_set_default(struct i2c_client *client, unsigned char core) | ||
612 | { | ||
613 | unsigned char tvp_reg_val = 0; | ||
614 | /* Core Write enable*/ | ||
615 | tvp5158_write(client, REG_DEC_WR_EN, core); | ||
616 | /* Set Video format */ | ||
617 | tvp_reg_val = TVP_INTERLEAVE_MODE_LINE | TVP_CH_MUX_NUMBER | ||
618 | | TVP_OUTPUT_TYPE | TVP_VCS_ID | TVP_VID_RES; | ||
619 | tvp5158_write(client, REG_AVD_CTRL_1, tvp_reg_val); | ||
620 | tvp_reg_val = 0; | ||
621 | tvp_reg_val = TVP_ENABLE_DITHERING | TVP_VID_DET_SAVEAV_EN; | ||
622 | tvp5158_write(client, REG_AVD_CTRL_2, tvp_reg_val); | ||
623 | |||
624 | return 0; | ||
625 | } | ||
626 | |||
627 | static enum tvp5158_std | ||
628 | tvp5158_get_video_std(struct i2c_client *client, unsigned char core) | ||
629 | { | ||
630 | struct tvp5158_priv *priv = to_tvp5158(client); | ||
631 | int i2c_read = 0; | ||
632 | |||
633 | /* Core Read Enable */ | ||
634 | tvp5158_write(client, REG_DEC_RD_EN, core); | ||
635 | /* Get Video Status */ | ||
636 | i2c_read = tvp5158_read(client, REG_STAUS_2); | ||
637 | v4l2_dbg(1, debug, &priv->subdev, "%s\n", | ||
638 | (i2c_read & TVP_SIGNAL_PRESENT) ? | ||
639 | "Signal Present" : "Signal not present"); | ||
640 | |||
641 | if (!(i2c_read & TVP_SIGNAL_PRESENT)) { | ||
642 | priv->current_std = STD_INVALID; | ||
643 | goto fail; | ||
644 | } | ||
645 | |||
646 | i2c_read = tvp5158_read(client, REG_VID_STAND); | ||
647 | |||
648 | if ((i2c_read & TVP_VIDEO_STANDARD_MASK) == 0x1) { | ||
649 | |||
650 | priv->current_std = STD_NTSC_MJ; | ||
651 | v4l2_info(&priv->subdev, "NTSC video detected\n"); | ||
652 | } else if ((i2c_read & TVP_VIDEO_STANDARD_MASK) == 0x2) { | ||
653 | |||
654 | priv->current_std = STD_PAL_BDGHIN; | ||
655 | v4l2_info(&priv->subdev, "PAL video detected\n"); | ||
656 | } else { | ||
657 | v4l2_err(&priv->subdev, "No video detected\n"); | ||
658 | priv->current_std = STD_INVALID; | ||
659 | } | ||
660 | |||
661 | fail: | ||
662 | return priv->current_std; | ||
663 | } | ||
664 | |||
665 | static void | ||
666 | tvp5158_start_streaming(struct i2c_client *client, unsigned char core) | ||
667 | { | ||
668 | unsigned char tvp_reg_val = 0; | ||
669 | |||
670 | /* Decoder Write Enable */ | ||
671 | tvp5158_write(client, REG_DEC_WR_EN, core); | ||
672 | /* Enable output stream on */ | ||
673 | tvp_reg_val = TVP_VIDEO_PORT_ENABLE | TVP_OUT_CLK_P_EN; | ||
674 | tvp5158_write(client, REG_OFM_CTRL, tvp_reg_val); | ||
675 | |||
676 | } | ||
677 | |||
678 | static int tvp5158_probe(struct i2c_client *client, | ||
679 | const struct i2c_device_id *did) | ||
680 | { | ||
681 | struct tvp5158_priv *priv; | ||
682 | struct v4l2_subdev *sd; | ||
683 | struct device_node *node = client->dev.of_node; | ||
684 | int ret = -1; | ||
685 | int i2c_read; | ||
686 | union { | ||
687 | char buff[4]; | ||
688 | int buffer; | ||
689 | } u_i2cbuf; | ||
690 | |||
691 | priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); | ||
692 | if (!priv) | ||
693 | return -ENOMEM; | ||
694 | i2c_set_clientdata(client, priv); | ||
695 | |||
696 | sd = &priv->subdev; | ||
697 | |||
698 | v4l2_i2c_subdev_init(sd, client, &tvp5158_subdev_ops); | ||
699 | |||
700 | ret = tvp5158_of_probe(client, node); | ||
701 | if (ret) { | ||
702 | dev_err(&client->dev, "Unable to of_probe\n"); | ||
703 | return ret; | ||
704 | } | ||
705 | |||
706 | ret = tvp5158_init_gpios(client); | ||
707 | if (ret) { | ||
708 | dev_err(&client->dev, "failed to init gpios ERR %d\n", ret); | ||
709 | return ret; | ||
710 | } | ||
711 | |||
712 | priv->current_std = STD_INVALID; | ||
713 | priv->format.code = tvp5158_cfmts[0].code; | ||
714 | priv->format.colorspace = tvp5158_cfmts[0].colorspace; | ||
715 | priv->format.field = V4L2_FIELD_ALTERNATE; | ||
716 | |||
717 | /* Get Chip ID and register with v4l2*/ | ||
718 | i2c_read = tvp5158_read(client, REG_CHIPID_MSB); | ||
719 | u_i2cbuf.buffer = i2c_read << 8; | ||
720 | i2c_read = tvp5158_read(client, REG_CHIPID_LSB); | ||
721 | u_i2cbuf.buffer |= i2c_read; | ||
722 | if (u_i2cbuf.buffer == 0x5158) { | ||
723 | v4l2_dbg(1, debug, sd, "Chip id : %x\n", u_i2cbuf.buffer); | ||
724 | tvp5158_write(client, REG_DEC_WR_EN, TVP_CORE_ALL); | ||
725 | tvp5158_write(client, REG_OFM_CTRL, | ||
726 | (TVP_VIDEO_PORT_ENABLE | TVP_OUT_CLK_P_EN)); | ||
727 | } else { | ||
728 | dev_err(&client->dev, "ERROR: Chip id is not TVP5158"); | ||
729 | return -ENODEV; | ||
730 | } | ||
731 | |||
732 | tvp5158_set_default(client, TVP_CORE_ALL); | ||
733 | tvp5158_get_video_std(client, TVP_CORE_ALL); | ||
734 | |||
735 | /* V4l2 asyn subdev register */ | ||
736 | sd->dev = &client->dev; | ||
737 | ret = v4l2_async_register_subdev(sd); | ||
738 | if (!ret) | ||
739 | v4l2_info(&priv->subdev, "Camera sensor driver registered\n"); | ||
740 | else | ||
741 | return ret; | ||
742 | |||
743 | pm_runtime_enable(&client->dev); | ||
744 | |||
745 | return ret; | ||
746 | } | ||
747 | |||
748 | static int tvp5158_remove(struct i2c_client *client) | ||
749 | { | ||
750 | struct tvp5158_priv *priv = i2c_get_clientdata(client); | ||
751 | |||
752 | v4l2_device_unregister_subdev(&priv->subdev); | ||
753 | return 0; | ||
754 | } | ||
755 | |||
756 | static struct i2c_driver tvp5158_i2c_driver = { | ||
757 | .driver = { | ||
758 | .owner = THIS_MODULE, | ||
759 | .name = "tvp5158", | ||
760 | .of_match_table = tvp5158_dt_id, | ||
761 | }, | ||
762 | .probe = tvp5158_probe, | ||
763 | .remove = tvp5158_remove, | ||
764 | .id_table = tvp5158_id, | ||
765 | }; | ||
766 | |||
767 | module_i2c_driver(tvp5158_i2c_driver); | ||
768 | |||
769 | MODULE_DESCRIPTION("Video Decoder driver"); | ||
770 | MODULE_AUTHOR("Sathishkumar S"); | ||
771 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 033b7dbf3d67..182a9089b996 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig | |||
@@ -303,6 +303,27 @@ config VIDEO_TI_VPE_DEBUG | |||
303 | 303 | ||
304 | endif # V4L_MEM2MEM_DRIVERS | 304 | endif # V4L_MEM2MEM_DRIVERS |
305 | 305 | ||
306 | config VIDEO_TI_VPDMA_HELPER | ||
307 | tristate "TI VPDMA helper module" | ||
308 | depends on VIDEO_TI_VIP || VIDEO_TI_VPE | ||
309 | default n | ||
310 | ---help--- | ||
311 | Video Port Direct Memory Access | ||
312 | Used with VIP and VPE on some TI SoC's (e.g. DRA7xx) | ||
313 | it provides a mem2mem, mem2device, device2mem DMA specifically | ||
314 | for transferring and manipulating video data. | ||
315 | |||
316 | config VIDEO_TI_VPDMA_LOAD_FW | ||
317 | bool "Load VPDMA F/W from Kernel" | ||
318 | depends on VIDEO_TI_VPDMA_HELPER | ||
319 | default n | ||
320 | ---help--- | ||
321 | TI SoC's Video Port Direct Memory Access module | ||
322 | needs a firmware to be loaded. This can be loaded from | ||
323 | user space via udev event or it can be loaded from kernel itself | ||
324 | Say 'y' if you want the Video devices to be initialized early | ||
325 | in the bootup sequence. | ||
326 | |||
306 | config VIDEO_TI_VPDMA | 327 | config VIDEO_TI_VPDMA |
307 | tristate | 328 | tristate |
308 | 329 | ||
diff --git a/drivers/media/platform/ti-vpe/vip.c b/drivers/media/platform/ti-vpe/vip.c index 9070e160d166..50d461f53f79 100644 --- a/drivers/media/platform/ti-vpe/vip.c +++ b/drivers/media/platform/ti-vpe/vip.c | |||
@@ -1592,6 +1592,15 @@ static int vip_try_fmt_vid_cap(struct file *file, void *priv, | |||
1592 | if (ret) | 1592 | if (ret) |
1593 | break; | 1593 | break; |
1594 | 1594 | ||
1595 | /* For interlaced capture, enum_frame size = FRAME size | ||
1596 | * while f->fmt.pix = FIELD size | ||
1597 | * Correct the subdev returned height params | ||
1598 | */ | ||
1599 | if (f->fmt.pix.field == V4L2_FIELD_ALTERNATE) { | ||
1600 | fse.min_height /= 2; | ||
1601 | fse.max_height /= 2; | ||
1602 | } | ||
1603 | |||
1595 | vip_dbg(3, dev, "try_fmt loop:%d fourcc:%s size: %dx%d\n", | 1604 | vip_dbg(3, dev, "try_fmt loop:%d fourcc:%s size: %dx%d\n", |
1596 | fse.index, fourcc_to_str(f->fmt.pix.pixelformat), | 1605 | fse.index, fourcc_to_str(f->fmt.pix.pixelformat), |
1597 | fse.max_width, fse.max_height); | 1606 | fse.max_width, fse.max_height); |
@@ -2691,9 +2700,11 @@ static int vip_init_port(struct vip_port *port) | |||
2691 | sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; | 2700 | sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; |
2692 | sd_fmt.pad = 0; | 2701 | sd_fmt.pad = 0; |
2693 | ret = v4l2_subdev_call(port->subdev, pad, get_fmt, NULL, &sd_fmt); | 2702 | ret = v4l2_subdev_call(port->subdev, pad, get_fmt, NULL, &sd_fmt); |
2694 | if (ret) | 2703 | if (ret) { |
2695 | vip_dbg(1, dev, "init_port get_fmt failed in subdev: (%d)\n", | 2704 | vip_dbg(1, dev, "init_port get_fmt failed in subdev: (%d)\n", |
2696 | ret); | 2705 | ret); |
2706 | return ret; | ||
2707 | } | ||
2697 | 2708 | ||
2698 | /* try to find one that matches */ | 2709 | /* try to find one that matches */ |
2699 | fmt = find_port_format_by_code(port, mbus_fmt->code); | 2710 | fmt = find_port_format_by_code(port, mbus_fmt->code); |
@@ -3085,8 +3096,10 @@ static int vip_open(struct file *file) | |||
3085 | if (!v4l2_fh_is_singular_file(file)) | 3096 | if (!v4l2_fh_is_singular_file(file)) |
3086 | goto unlock; | 3097 | goto unlock; |
3087 | 3098 | ||
3088 | if (vip_init_stream(stream)) | 3099 | if (vip_init_stream(stream)) { |
3100 | v4l2_fh_release(file); | ||
3089 | ret = -ENODEV; | 3101 | ret = -ENODEV; |
3102 | } | ||
3090 | unlock: | 3103 | unlock: |
3091 | mutex_unlock(&dev->mutex); | 3104 | mutex_unlock(&dev->mutex); |
3092 | return ret; | 3105 | return ret; |
diff --git a/drivers/of/base.c b/drivers/of/base.c index 31341290cd91..96d3cb526823 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -1739,6 +1739,7 @@ int of_add_property(struct device_node *np, struct property *prop) | |||
1739 | 1739 | ||
1740 | return rc; | 1740 | return rc; |
1741 | } | 1741 | } |
1742 | EXPORT_SYMBOL_GPL(of_remove_property); | ||
1742 | 1743 | ||
1743 | int __of_remove_property(struct device_node *np, struct property *prop) | 1744 | int __of_remove_property(struct device_node *np, struct property *prop) |
1744 | { | 1745 | { |
diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c index 39af14e958a2..5d6f17bdfb2f 100644 --- a/drivers/remoteproc/omap_remoteproc.c +++ b/drivers/remoteproc/omap_remoteproc.c | |||
@@ -436,6 +436,10 @@ static int omap_rproc_start(struct rproc *rproc) | |||
436 | int ret; | 436 | int ret; |
437 | struct mbox_client *client = &oproc->client; | 437 | struct mbox_client *client = &oproc->client; |
438 | 438 | ||
439 | /* | ||
440 | * We set boot address irrespective of the value of the late attach flag | ||
441 | * as boot address takes effect only on a deassert of remoteproc reset. | ||
442 | */ | ||
439 | if (oproc->boot_data) { | 443 | if (oproc->boot_data) { |
440 | ret = omap_rproc_write_dsp_boot_addr(rproc); | 444 | ret = omap_rproc_write_dsp_boot_addr(rproc); |
441 | if (ret) | 445 | if (ret) |
@@ -475,10 +479,12 @@ static int omap_rproc_start(struct rproc *rproc) | |||
475 | goto put_mbox; | 479 | goto put_mbox; |
476 | } | 480 | } |
477 | 481 | ||
478 | ret = pdata->device_enable(pdev); | 482 | if (!rproc->late_attach) { |
479 | if (ret) { | 483 | ret = pdata->device_enable(pdev); |
480 | dev_err(dev, "omap_device_enable failed: %d\n", ret); | 484 | if (ret) { |
481 | goto reset_timers; | 485 | dev_err(dev, "omap_device_enable failed: %d\n", ret); |
486 | goto reset_timers; | ||
487 | } | ||
482 | } | 488 | } |
483 | 489 | ||
484 | /* | 490 | /* |
@@ -534,6 +540,16 @@ static int omap_rproc_stop(struct rproc *rproc) | |||
534 | if (ret) | 540 | if (ret) |
535 | goto enable_device; | 541 | goto enable_device; |
536 | 542 | ||
543 | /* | ||
544 | * During late attach, we use non-zeroing dma ops to prevent the kernel | ||
545 | * from overwriting already loaded code and data segments. When | ||
546 | * shutting down the processor, we restore the normal zeroing dma ops. | ||
547 | * This allows the kernel to clear memory when loading a new remoteproc | ||
548 | * binary or during error recovery with the current remoteproc binary. | ||
549 | */ | ||
550 | if (rproc->late_attach) | ||
551 | set_dma_ops(dev, &arm_dma_ops); | ||
552 | |||
537 | mbox_free_channel(oproc->mbox); | 553 | mbox_free_channel(oproc->mbox); |
538 | 554 | ||
539 | /* | 555 | /* |
@@ -1139,6 +1155,7 @@ static int omap_rproc_probe(struct platform_device *pdev) | |||
1139 | u32 standby_addr = 0; | 1155 | u32 standby_addr = 0; |
1140 | int num_timers; | 1156 | int num_timers; |
1141 | int ret; | 1157 | int ret; |
1158 | struct property *prop; | ||
1142 | 1159 | ||
1143 | if (!np) { | 1160 | if (!np) { |
1144 | dev_err(&pdev->dev, "only DT-based devices are supported\n"); | 1161 | dev_err(&pdev->dev, "only DT-based devices are supported\n"); |
@@ -1175,6 +1192,21 @@ static int omap_rproc_probe(struct platform_device *pdev) | |||
1175 | if (!rproc) | 1192 | if (!rproc) |
1176 | return -ENOMEM; | 1193 | return -ENOMEM; |
1177 | 1194 | ||
1195 | prop = of_find_property(np, "ti,late-attach", NULL); | ||
1196 | if (prop) { | ||
1197 | rproc->late_attach = 1; | ||
1198 | set_dma_ops(&pdev->dev, &arm_dma_m_ops); | ||
1199 | dev_dbg(&pdev->dev, "device will be late-attached\n"); | ||
1200 | |||
1201 | /* | ||
1202 | * Clear the late attach property in device tree for | ||
1203 | * subsequent probes. | ||
1204 | */ | ||
1205 | ret = of_remove_property(np, prop); | ||
1206 | if (ret) | ||
1207 | dev_err(&pdev->dev, "Unable to remove late-attach property\n"); | ||
1208 | } | ||
1209 | |||
1178 | oproc = rproc->priv; | 1210 | oproc = rproc->priv; |
1179 | oproc->rproc = rproc; | 1211 | oproc->rproc = rproc; |
1180 | /* All existing OMAP IPU and DSP processors have an MMU */ | 1212 | /* All existing OMAP IPU and DSP processors have an MMU */ |
@@ -1282,6 +1314,8 @@ static int omap_rproc_probe(struct platform_device *pdev) | |||
1282 | release_mem: | 1314 | release_mem: |
1283 | of_reserved_mem_device_release(&pdev->dev); | 1315 | of_reserved_mem_device_release(&pdev->dev); |
1284 | free_rproc: | 1316 | free_rproc: |
1317 | if (rproc->late_attach) | ||
1318 | set_dma_ops(&pdev->dev, &arm_dma_ops); | ||
1285 | rproc_put(rproc); | 1319 | rproc_put(rproc); |
1286 | return ret; | 1320 | return ret; |
1287 | } | 1321 | } |
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index a1804e236217..8d33bb5d9c3b 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c | |||
@@ -223,7 +223,11 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i) | |||
223 | * Allocate non-cacheable memory for the vring. In the future | 223 | * Allocate non-cacheable memory for the vring. In the future |
224 | * this call will also configure the IOMMU for us | 224 | * this call will also configure the IOMMU for us |
225 | */ | 225 | */ |
226 | va = dma_alloc_coherent(dev->parent, size, &dma, GFP_KERNEL); | 226 | if (rproc->late_attach) { |
227 | va = dma_malloc_coherent(dev->parent, size, &dma, GFP_KERNEL); | ||
228 | } else { | ||
229 | va = dma_alloc_coherent(dev->parent, size, &dma, GFP_KERNEL); | ||
230 | } | ||
227 | if (!va) { | 231 | if (!va) { |
228 | dev_err(dev->parent, "dma_alloc_coherent failed\n"); | 232 | dev_err(dev->parent, "dma_alloc_coherent failed\n"); |
229 | return -EINVAL; | 233 | return -EINVAL; |
@@ -670,10 +674,13 @@ static int rproc_handle_devmem(struct rproc *rproc, struct fw_rsc_devmem *rsc, | |||
670 | if (!mapping) | 674 | if (!mapping) |
671 | return -ENOMEM; | 675 | return -ENOMEM; |
672 | 676 | ||
673 | ret = iommu_map(rproc->domain, rsc->da, rsc->pa, rsc->len, rsc->flags); | 677 | if (!rproc->late_attach) { |
674 | if (ret) { | 678 | ret = iommu_map(rproc->domain, rsc->da, rsc->pa, rsc->len, |
675 | dev_err(dev, "failed to map devmem: %d\n", ret); | 679 | rsc->flags); |
676 | goto out; | 680 | if (ret) { |
681 | dev_err(dev, "failed to map devmem: %d\n", ret); | ||
682 | goto out; | ||
683 | } | ||
677 | } | 684 | } |
678 | 685 | ||
679 | /* | 686 | /* |
@@ -688,8 +695,12 @@ static int rproc_handle_devmem(struct rproc *rproc, struct fw_rsc_devmem *rsc, | |||
688 | mapping->len = rsc->len; | 695 | mapping->len = rsc->len; |
689 | list_add_tail(&mapping->node, &rproc->mappings); | 696 | list_add_tail(&mapping->node, &rproc->mappings); |
690 | 697 | ||
691 | dev_dbg(dev, "mapped devmem pa 0x%x, da 0x%x, len 0x%x\n", | 698 | if (!rproc->late_attach) |
692 | rsc->pa, rsc->da, rsc->len); | 699 | dev_dbg(dev, "mapped devmem pa 0x%x, da 0x%x, len 0x%x\n", |
700 | rsc->pa, rsc->da, rsc->len); | ||
701 | else | ||
702 | dev_dbg(dev, "late-attach: processed devmem pa 0x%x, da 0x%x, len 0x%x\n", | ||
703 | rsc->pa, rsc->da, rsc->len); | ||
693 | 704 | ||
694 | return 0; | 705 | return 0; |
695 | 706 | ||
@@ -744,7 +755,11 @@ static int rproc_handle_carveout(struct rproc *rproc, | |||
744 | if (!carveout) | 755 | if (!carveout) |
745 | return -ENOMEM; | 756 | return -ENOMEM; |
746 | 757 | ||
747 | va = dma_alloc_coherent(dev->parent, rsc->len, &dma, GFP_KERNEL); | 758 | if (rproc->late_attach) { |
759 | va = dma_malloc_coherent(dev->parent, rsc->len, &dma, GFP_KERNEL); | ||
760 | } else { | ||
761 | va = dma_alloc_coherent(dev->parent, rsc->len, &dma, GFP_KERNEL); | ||
762 | } | ||
748 | if (!va) { | 763 | if (!va) { |
749 | dev_err(dev->parent, "dma_alloc_coherent err: %d\n", rsc->len); | 764 | dev_err(dev->parent, "dma_alloc_coherent err: %d\n", rsc->len); |
750 | ret = -ENOMEM; | 765 | ret = -ENOMEM; |
@@ -779,11 +794,13 @@ static int rproc_handle_carveout(struct rproc *rproc, | |||
779 | goto dma_free; | 794 | goto dma_free; |
780 | } | 795 | } |
781 | 796 | ||
782 | ret = iommu_map(rproc->domain, rsc->da, dma, rsc->len, | 797 | if (!rproc->late_attach) { |
783 | rsc->flags); | 798 | ret = iommu_map(rproc->domain, rsc->da, dma, rsc->len, |
784 | if (ret) { | 799 | rsc->flags); |
785 | dev_err(dev, "iommu_map failed: %d\n", ret); | 800 | if (ret) { |
786 | goto free_mapping; | 801 | dev_err(dev, "iommu_map failed: %d\n", ret); |
802 | goto free_mapping; | ||
803 | } | ||
787 | } | 804 | } |
788 | 805 | ||
789 | /* | 806 | /* |
@@ -797,8 +814,14 @@ static int rproc_handle_carveout(struct rproc *rproc, | |||
797 | mapping->len = rsc->len; | 814 | mapping->len = rsc->len; |
798 | list_add_tail(&mapping->node, &rproc->mappings); | 815 | list_add_tail(&mapping->node, &rproc->mappings); |
799 | 816 | ||
800 | dev_dbg(dev, "carveout mapped 0x%x to %pad\n", | 817 | if (!rproc->late_attach) |
801 | rsc->da, &dma); | 818 | dev_dbg(dev, "carveout mapped 0x%x to %pad\n", |
819 | rsc->da, &dma); | ||
820 | else | ||
821 | dev_dbg(dev, "late-attach: carveout processed " | ||
822 | "0x%x to %pad\n", | ||
823 | rsc->da, &dma); | ||
824 | |||
802 | } | 825 | } |
803 | 826 | ||
804 | /* | 827 | /* |
@@ -1011,11 +1034,14 @@ static void rproc_resource_cleanup(struct rproc *rproc) | |||
1011 | list_for_each_entry_safe(entry, tmp, &rproc->mappings, node) { | 1034 | list_for_each_entry_safe(entry, tmp, &rproc->mappings, node) { |
1012 | size_t unmapped; | 1035 | size_t unmapped; |
1013 | 1036 | ||
1014 | unmapped = iommu_unmap(rproc->domain, entry->da, entry->len); | 1037 | if (!rproc->late_attach) { |
1015 | if (unmapped != entry->len) { | 1038 | unmapped = iommu_unmap(rproc->domain, entry->da, |
1016 | /* nothing much to do besides complaining */ | 1039 | entry->len); |
1017 | dev_err(dev, "failed to unmap %u/%zu\n", entry->len, | 1040 | if (unmapped != entry->len) { |
1018 | unmapped); | 1041 | /* nothing much to do besides complaining */ |
1042 | dev_err(dev, "failed to unmap %u/%zu\n", | ||
1043 | entry->len, unmapped); | ||
1044 | } | ||
1019 | } | 1045 | } |
1020 | 1046 | ||
1021 | list_del(&entry->node); | 1047 | list_del(&entry->node); |
@@ -1100,7 +1126,7 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw) | |||
1100 | } | 1126 | } |
1101 | } | 1127 | } |
1102 | 1128 | ||
1103 | if (!rproc->use_userspace_loader) { | 1129 | if ((!rproc->use_userspace_loader) && (!rproc->late_attach)) { |
1104 | /* load the ELF segments to memory */ | 1130 | /* load the ELF segments to memory */ |
1105 | ret = rproc_load_segments(rproc, fw); | 1131 | ret = rproc_load_segments(rproc, fw); |
1106 | if (ret) { | 1132 | if (ret) { |
@@ -1108,6 +1134,8 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw) | |||
1108 | ret); | 1134 | ret); |
1109 | goto clean_up; | 1135 | goto clean_up; |
1110 | } | 1136 | } |
1137 | } else { | ||
1138 | dev_dbg(dev, "late-attach: skipping segment load\n"); | ||
1111 | } | 1139 | } |
1112 | 1140 | ||
1113 | /* | 1141 | /* |
@@ -1504,6 +1532,7 @@ void rproc_shutdown(struct rproc *rproc) | |||
1504 | complete_all(&rproc->crash_comp); | 1532 | complete_all(&rproc->crash_comp); |
1505 | 1533 | ||
1506 | rproc->state = RPROC_OFFLINE; | 1534 | rproc->state = RPROC_OFFLINE; |
1535 | rproc->late_attach = 0; | ||
1507 | 1536 | ||
1508 | dev_info(dev, "stopped remote processor %s\n", rproc->name); | 1537 | dev_info(dev, "stopped remote processor %s\n", rproc->name); |
1509 | 1538 | ||
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c index c9fcbf063794..361a6d8aa297 100644 --- a/drivers/rpmsg/virtio_rpmsg_bus.c +++ b/drivers/rpmsg/virtio_rpmsg_bus.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/jiffies.h> | 31 | #include <linux/jiffies.h> |
32 | #include <linux/sched.h> | 32 | #include <linux/sched.h> |
33 | #include <linux/wait.h> | 33 | #include <linux/wait.h> |
34 | #include <linux/remoteproc.h> | ||
34 | #include <linux/rpmsg.h> | 35 | #include <linux/rpmsg.h> |
35 | #include <linux/mutex.h> | 36 | #include <linux/mutex.h> |
36 | 37 | ||
@@ -408,8 +409,11 @@ static int rpmsg_dev_probe(struct device *dev) | |||
408 | nsm.flags = RPMSG_NS_CREATE; | 409 | nsm.flags = RPMSG_NS_CREATE; |
409 | 410 | ||
410 | err = rpmsg_sendto(rpdev, &nsm, sizeof(nsm), RPMSG_NS_ADDR); | 411 | err = rpmsg_sendto(rpdev, &nsm, sizeof(nsm), RPMSG_NS_ADDR); |
411 | if (err) | 412 | if (err) { |
412 | dev_err(dev, "failed to announce service %d\n", err); | 413 | dev_err(dev, "failed to announce service %d\n", err); |
414 | rpdrv->remove(rpdev); | ||
415 | rpmsg_destroy_ept(ept); | ||
416 | } | ||
413 | } | 417 | } |
414 | 418 | ||
415 | out: | 419 | out: |
@@ -570,6 +574,13 @@ struct rpmsg_channel *__rpmsg_create_channel(struct virtproc_info *vrp, | |||
570 | return NULL; | 574 | return NULL; |
571 | } | 575 | } |
572 | 576 | ||
577 | if (!rpdev->ept) { | ||
578 | dev_err(dev, "failed to create ept\n"); | ||
579 | device_unregister(&rpdev->dev); | ||
580 | put_device(&rpdev->dev); | ||
581 | return NULL; | ||
582 | } | ||
583 | |||
573 | return rpdev; | 584 | return rpdev; |
574 | } | 585 | } |
575 | 586 | ||
@@ -1060,6 +1071,7 @@ static int rpmsg_probe(struct virtio_device *vdev) | |||
1060 | int err = 0, i; | 1071 | int err = 0, i; |
1061 | size_t total_buf_space; | 1072 | size_t total_buf_space; |
1062 | bool notify; | 1073 | bool notify; |
1074 | struct rproc *rproc = rproc_vdev_to_rproc_safe(vdev); | ||
1063 | 1075 | ||
1064 | vrp = kzalloc(sizeof(*vrp), GFP_KERNEL); | 1076 | vrp = kzalloc(sizeof(*vrp), GFP_KERNEL); |
1065 | if (!vrp) | 1077 | if (!vrp) |
@@ -1093,9 +1105,15 @@ static int rpmsg_probe(struct virtio_device *vdev) | |||
1093 | total_buf_space = vrp->num_bufs * RPMSG_BUF_SIZE; | 1105 | total_buf_space = vrp->num_bufs * RPMSG_BUF_SIZE; |
1094 | 1106 | ||
1095 | /* allocate coherent memory for the buffers */ | 1107 | /* allocate coherent memory for the buffers */ |
1096 | bufs_va = dma_alloc_coherent(vdev->dev.parent->parent, | 1108 | if (rproc && rproc->late_attach) |
1097 | total_buf_space, &vrp->bufs_dma, | 1109 | bufs_va = dma_malloc_coherent(vdev->dev.parent->parent, |
1098 | GFP_KERNEL); | 1110 | total_buf_space, &vrp->bufs_dma, |
1111 | GFP_KERNEL); | ||
1112 | else | ||
1113 | bufs_va = dma_alloc_coherent(vdev->dev.parent->parent, | ||
1114 | total_buf_space, &vrp->bufs_dma, | ||
1115 | GFP_KERNEL); | ||
1116 | |||
1099 | if (!bufs_va) { | 1117 | if (!bufs_va) { |
1100 | err = -ENOMEM; | 1118 | err = -ENOMEM; |
1101 | goto vqs_del; | 1119 | goto vqs_del; |
diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index ac34acd7bb93..5c60bf4423e6 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c | |||
@@ -250,8 +250,7 @@ static int tee_ioctl_open_session(struct tee_context *ctx, | |||
250 | buf.buf_len < sizeof(struct tee_ioctl_open_session_arg)) | 250 | buf.buf_len < sizeof(struct tee_ioctl_open_session_arg)) |
251 | return -EINVAL; | 251 | return -EINVAL; |
252 | 252 | ||
253 | uarg = (struct tee_ioctl_open_session_arg __user *)(unsigned long) | 253 | uarg = u64_to_user_ptr(buf.buf_ptr); |
254 | buf.buf_ptr; | ||
255 | if (copy_from_user(&arg, uarg, sizeof(arg))) | 254 | if (copy_from_user(&arg, uarg, sizeof(arg))) |
256 | return -EFAULT; | 255 | return -EFAULT; |
257 | 256 | ||
@@ -322,8 +321,7 @@ static int tee_ioctl_invoke(struct tee_context *ctx, | |||
322 | buf.buf_len < sizeof(struct tee_ioctl_invoke_arg)) | 321 | buf.buf_len < sizeof(struct tee_ioctl_invoke_arg)) |
323 | return -EINVAL; | 322 | return -EINVAL; |
324 | 323 | ||
325 | uarg = (struct tee_ioctl_invoke_arg __user *)(unsigned long) | 324 | uarg = u64_to_user_ptr(buf.buf_ptr); |
326 | buf.buf_ptr; | ||
327 | if (copy_from_user(&arg, uarg, sizeof(arg))) | 325 | if (copy_from_user(&arg, uarg, sizeof(arg))) |
328 | return -EFAULT; | 326 | return -EFAULT; |
329 | 327 | ||
@@ -457,8 +455,7 @@ static int tee_ioctl_supp_recv(struct tee_context *ctx, | |||
457 | buf.buf_len < sizeof(struct tee_iocl_supp_recv_arg)) | 455 | buf.buf_len < sizeof(struct tee_iocl_supp_recv_arg)) |
458 | return -EINVAL; | 456 | return -EINVAL; |
459 | 457 | ||
460 | uarg = (struct tee_iocl_supp_recv_arg __user *)(unsigned long) | 458 | uarg = u64_to_user_ptr(buf.buf_ptr); |
461 | buf.buf_ptr; | ||
462 | if (get_user(num_params, &uarg->num_params)) | 459 | if (get_user(num_params, &uarg->num_params)) |
463 | return -EFAULT; | 460 | return -EFAULT; |
464 | 461 | ||
@@ -552,8 +549,7 @@ static int tee_ioctl_supp_send(struct tee_context *ctx, | |||
552 | buf.buf_len < sizeof(struct tee_iocl_supp_send_arg)) | 549 | buf.buf_len < sizeof(struct tee_iocl_supp_send_arg)) |
553 | return -EINVAL; | 550 | return -EINVAL; |
554 | 551 | ||
555 | uarg = (struct tee_iocl_supp_send_arg __user *)(unsigned long) | 552 | uarg = u64_to_user_ptr(buf.buf_ptr); |
556 | buf.buf_ptr; | ||
557 | if (get_user(ret, &uarg->ret) || | 553 | if (get_user(ret, &uarg->ret) || |
558 | get_user(num_params, &uarg->num_params)) | 554 | get_user(num_params, &uarg->num_params)) |
559 | return -EFAULT; | 555 | return -EFAULT; |
diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index 9ac37fe1b6a7..b07ab05bc05a 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/seq_file.h> | 25 | #include <linux/seq_file.h> |
26 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
27 | #include <linux/uaccess.h> | 27 | #include <linux/uaccess.h> |
28 | #include <linux/extcon.h> | ||
28 | 29 | ||
29 | #include <linux/usb/ch9.h> | 30 | #include <linux/usb/ch9.h> |
30 | 31 | ||
@@ -357,6 +358,61 @@ static const struct debugfs_reg32 dwc3_regs[] = { | |||
357 | dump_register(OSTS), | 358 | dump_register(OSTS), |
358 | }; | 359 | }; |
359 | 360 | ||
361 | /* List of detectable cables */ | ||
362 | enum { | ||
363 | EXTCON_CABLE_USB = 0, | ||
364 | EXTCON_CABLE_USB_HOST, | ||
365 | EXTCON_CABLE_END, | ||
366 | }; | ||
367 | |||
368 | static void usb_extcon_simulate_cable(struct dwc3 *dwc, enum usb_dr_mode mode) | ||
369 | { | ||
370 | const char *usb_extcon_cable[] = { | ||
371 | [EXTCON_CABLE_USB] = "USB", | ||
372 | [EXTCON_CABLE_USB_HOST] = "USB-HOST", | ||
373 | NULL, | ||
374 | }; | ||
375 | bool id, vbus; | ||
376 | |||
377 | if (!dwc->edev) | ||
378 | return; | ||
379 | |||
380 | /* set ID and VBUS based on usb-mode and update cable state */ | ||
381 | switch (mode) { | ||
382 | case USB_DR_MODE_HOST: | ||
383 | id = false; | ||
384 | vbus = false; | ||
385 | break; | ||
386 | case USB_DR_MODE_PERIPHERAL: | ||
387 | id = true; | ||
388 | vbus = true; | ||
389 | break; | ||
390 | case USB_DR_MODE_OTG: | ||
391 | id = false; | ||
392 | vbus = true; | ||
393 | break; | ||
394 | default: | ||
395 | return; | ||
396 | } | ||
397 | |||
398 | /* at first we clean states which are no longer active */ | ||
399 | if (id) | ||
400 | extcon_set_cable_state(dwc->edev, | ||
401 | usb_extcon_cable[EXTCON_CABLE_USB_HOST], false); | ||
402 | |||
403 | if (!vbus) | ||
404 | extcon_set_cable_state(dwc->edev, | ||
405 | usb_extcon_cable[EXTCON_CABLE_USB], false); | ||
406 | |||
407 | if (!id) | ||
408 | extcon_set_cable_state(dwc->edev, | ||
409 | usb_extcon_cable[EXTCON_CABLE_USB_HOST], true); | ||
410 | |||
411 | if (vbus) | ||
412 | extcon_set_cable_state(dwc->edev, | ||
413 | usb_extcon_cable[EXTCON_CABLE_USB], true); | ||
414 | } | ||
415 | |||
360 | static int dwc3_mode_show(struct seq_file *s, void *unused) | 416 | static int dwc3_mode_show(struct seq_file *s, void *unused) |
361 | { | 417 | { |
362 | struct dwc3 *dwc = s->private; | 418 | struct dwc3 *dwc = s->private; |
@@ -410,11 +466,22 @@ static ssize_t dwc3_mode_write(struct file *file, | |||
410 | if (!strncmp(buf, "otg", 3)) | 466 | if (!strncmp(buf, "otg", 3)) |
411 | mode |= DWC3_GCTL_PRTCAP_OTG; | 467 | mode |= DWC3_GCTL_PRTCAP_OTG; |
412 | 468 | ||
469 | if (dwc->dr_mode == USB_DR_MODE_OTG) { | ||
470 | if (mode & DWC3_GCTL_PRTCAP_HOST) | ||
471 | usb_extcon_simulate_cable(dwc, USB_DR_MODE_HOST); | ||
472 | else if (mode & DWC3_GCTL_PRTCAP_DEVICE) | ||
473 | usb_extcon_simulate_cable(dwc, USB_DR_MODE_PERIPHERAL); | ||
474 | else if (mode & DWC3_GCTL_PRTCAP_OTG) | ||
475 | usb_extcon_simulate_cable(dwc, USB_DR_MODE_OTG); | ||
476 | return count; | ||
477 | } | ||
478 | |||
413 | if (mode) { | 479 | if (mode) { |
414 | spin_lock_irqsave(&dwc->lock, flags); | 480 | spin_lock_irqsave(&dwc->lock, flags); |
415 | dwc3_set_mode(dwc, mode); | 481 | dwc3_set_mode(dwc, mode); |
416 | spin_unlock_irqrestore(&dwc->lock, flags); | 482 | spin_unlock_irqrestore(&dwc->lock, flags); |
417 | } | 483 | } |
484 | |||
418 | return count; | 485 | return count; |
419 | } | 486 | } |
420 | 487 | ||
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 35d239ebf912..138b0c33f959 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -31,6 +31,8 @@ endmenu | |||
31 | source "drivers/video/backlight/Kconfig" | 31 | source "drivers/video/backlight/Kconfig" |
32 | source "drivers/video/adf/Kconfig" | 32 | source "drivers/video/adf/Kconfig" |
33 | 33 | ||
34 | source "drivers/video/serdes/Kconfig" | ||
35 | |||
34 | config VGASTATE | 36 | config VGASTATE |
35 | tristate | 37 | tristate |
36 | default n | 38 | default n |
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 1a8c4ced39b2..80b5330c1b75 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
@@ -7,6 +7,7 @@ obj-$(CONFIG_LOGO) += logo/ | |||
7 | obj-y += backlight/ | 7 | obj-y += backlight/ |
8 | 8 | ||
9 | obj-y += fbdev/ | 9 | obj-y += fbdev/ |
10 | obj-y += serdes/ | ||
10 | 11 | ||
11 | obj-$(CONFIG_VIDEOMODE_HELPERS) += display_timing.o videomode.o | 12 | obj-$(CONFIG_VIDEOMODE_HELPERS) += display_timing.o videomode.o |
12 | ifeq ($(CONFIG_OF),y) | 13 | ifeq ($(CONFIG_OF),y) |
diff --git a/drivers/video/serdes/Kconfig b/drivers/video/serdes/Kconfig new file mode 100644 index 000000000000..84efb53bdab3 --- /dev/null +++ b/drivers/video/serdes/Kconfig | |||
@@ -0,0 +1,12 @@ | |||
1 | menu "Video Serializer Deserializer drivers" | ||
2 | |||
3 | config VIDEO_TI_FPD3_SERDES | ||
4 | tristate "Texas Instruments FPD link 3 serializer deserializer" | ||
5 | depends on I2C | ||
6 | help | ||
7 | This driver is used for configuring video serializers and | ||
8 | deserializers. When capturing video from a remote camera or | ||
9 | displaying to a remote display, the camera or display is | ||
10 | connected via FPDlink serializer / deserializer. | ||
11 | |||
12 | endmenu | ||
diff --git a/drivers/video/serdes/Makefile b/drivers/video/serdes/Makefile new file mode 100644 index 000000000000..eab69490ed5a --- /dev/null +++ b/drivers/video/serdes/Makefile | |||
@@ -0,0 +1,2 @@ | |||
1 | obj-$(CONFIG_VIDEO_TI_FPD3_SERDES) += ti-fpd3-serdes.o | ||
2 | ti-fpd3-serdes-y := fpd3_serdes.o fpd3_i2c_adap.o | ||
diff --git a/drivers/video/serdes/fpd3_i2c_adap.c b/drivers/video/serdes/fpd3_i2c_adap.c new file mode 100644 index 000000000000..8cc866fc1221 --- /dev/null +++ b/drivers/video/serdes/fpd3_i2c_adap.c | |||
@@ -0,0 +1,325 @@ | |||
1 | /* | ||
2 | * fpd3_i2c_adap.c | ||
3 | * | ||
4 | * lvds based serial link interface for onboard communication. | ||
5 | * Copyright (C) 2014-2015 Texas Instruments Incorporated - http://www.ti.com/ | ||
6 | * Authors: Nikhil Devshatwar <nikhil.nd@ti.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License version 2 as published by | ||
10 | * the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along with | ||
18 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | |||
21 | /* | ||
22 | * This file has helper functions to implement an i2c bus adapter driver for | ||
23 | * fpd3_serdes devices. Only the master device can communicate with the | ||
24 | * serializer and any other slaves connected at the remote end. | ||
25 | * | ||
26 | * Every i2c slave at the remote bus, can be accessed from linux i2c | ||
27 | * using aliases. Master device registers some aliases and maps them to the | ||
28 | * actual device addresses at remote bus. | ||
29 | * | ||
30 | * Any transactions addressed for these alias are detected by the master device | ||
31 | * and then recreated at the remote i2c bus with the real slave address. | ||
32 | * So in a way, master device acts as an i2c adapter driver for all the | ||
33 | * remote clients. | ||
34 | * | ||
35 | * This file implements an i2c adapter which just reroutes the transactions | ||
36 | * on the parent adapter with alias for the slave. | ||
37 | */ | ||
38 | |||
39 | #include <linux/kernel.h> | ||
40 | #include <linux/slab.h> | ||
41 | #include <linux/i2c.h> | ||
42 | #include <linux/delay.h> | ||
43 | #include "fpd3_serdes.h" | ||
44 | |||
45 | static int fpd3_serdes_setup_aliases(struct i2c_client *client) | ||
46 | { | ||
47 | struct fpd3_serdes_data *data = i2c_get_clientdata(client); | ||
48 | const struct fpd3_serdes_platform_data *pdata = data->pdata; | ||
49 | int i = 0, ret, count = 0; | ||
50 | u8 reg; | ||
51 | |||
52 | /* | ||
53 | * First entry is for the remote serdes and any further entries | ||
54 | * are for the slaves connected at remote bus | ||
55 | */ | ||
56 | for (i = 0; i < data->num_slaves; i++) { | ||
57 | |||
58 | if (data->slave_addr[i] == 0) | ||
59 | continue; | ||
60 | /* Setup the real slave address */ | ||
61 | if (i == 0) | ||
62 | reg = pdata->dev_type == FPD3_SER_DEV ? | ||
63 | FPD3_SER_DES_ID : FPD3_DES_SER_ID; | ||
64 | else { | ||
65 | reg = pdata->dev_type == FPD3_SER_DEV ? | ||
66 | FPD3_SER_SLAVE_ID0 : FPD3_DES_SLAVE_ID0; | ||
67 | reg += i - 1; | ||
68 | } | ||
69 | ret = i2c_write_le8(client, reg, data->slave_addr[i] << 1); | ||
70 | if (ret < 0) | ||
71 | goto error_setup; | ||
72 | |||
73 | /* Setup the alias for the slave */ | ||
74 | if (i == 0) | ||
75 | reg = pdata->dev_type == FPD3_SER_DEV ? | ||
76 | FPD3_SER_DES_AL : FPD3_DES_SER_AL; | ||
77 | else { | ||
78 | reg = pdata->dev_type == FPD3_SER_DEV ? | ||
79 | FPD3_SER_SLAVE_AL0 : FPD3_DES_SLAVE_AL0; | ||
80 | reg += + i - 1; | ||
81 | } | ||
82 | ret = i2c_write_le8(client, reg, data->slave_alias[i] << 1); | ||
83 | if (ret < 0) | ||
84 | goto error_setup; | ||
85 | |||
86 | dev_dbg(&client->dev, "Registered alias 0x%2x for 0x%02x", | ||
87 | data->slave_alias[i], data->slave_addr[i]); | ||
88 | } | ||
89 | |||
90 | while (count < FPD3_MAX_POLL_COUNT) { | ||
91 | |||
92 | reg = pdata->dev_type == FPD3_SER_DEV ? | ||
93 | FPD3_SER_GN_STS : FPD3_DES_GN_STS; | ||
94 | ret = i2c_read_le8(client, reg); | ||
95 | if (ret < 0) | ||
96 | return ret; | ||
97 | if (ret & SIGNAL_DETECT) | ||
98 | break; | ||
99 | udelay(10); | ||
100 | count++; | ||
101 | } | ||
102 | |||
103 | if (count >= FPD3_MAX_POLL_COUNT) { | ||
104 | dev_err(&client->dev, "Unable to sync with remote slave"); | ||
105 | return -EIO; | ||
106 | } | ||
107 | |||
108 | dev_dbg(&client->dev, "Remote signal detected"); | ||
109 | return 0; | ||
110 | error_setup: | ||
111 | dev_err(&client->dev, "Failed to setup alias for %2x", | ||
112 | data->slave_addr[i]); | ||
113 | return ret; | ||
114 | } | ||
115 | |||
116 | static int setup_link(struct i2c_adapter *adap) | ||
117 | { | ||
118 | struct i2c_client *client = i2c_get_adapdata(adap); | ||
119 | struct fpd3_serdes_data *data = i2c_get_clientdata(client); | ||
120 | int ret; | ||
121 | |||
122 | if (data->link_ok) | ||
123 | return 0; | ||
124 | else if (data->link_ok < 0) | ||
125 | return data->link_ok; | ||
126 | |||
127 | ret = fpd3_serdes_initialize(client); | ||
128 | if (ret == 0) | ||
129 | ret = fpd3_serdes_setup_aliases(client); | ||
130 | if (ret == 0) | ||
131 | data->link_ok = 1; | ||
132 | else | ||
133 | data->link_ok = -EIO; | ||
134 | return ret; | ||
135 | } | ||
136 | |||
137 | static u8 fpd3_alloc_addr(struct i2c_adapter *adap, u8 addr) | ||
138 | { | ||
139 | struct i2c_client *client = i2c_get_adapdata(adap); | ||
140 | struct fpd3_serdes_data *data = i2c_get_clientdata(client); | ||
141 | const struct fpd3_serdes_platform_data *pdata = data->pdata; | ||
142 | u8 reg, i; | ||
143 | |||
144 | for (i = 0; i < data->num_slaves; i++) { | ||
145 | if (data->slave_addr[i] == 0x0) | ||
146 | break; | ||
147 | } | ||
148 | if (i < data->num_slaves) { | ||
149 | |||
150 | /* Program new mapping for remote address and alias */ | ||
151 | reg = pdata->dev_type == FPD3_SER_DEV ? | ||
152 | FPD3_SER_SLAVE_ID0 : FPD3_DES_SLAVE_ID0; | ||
153 | i2c_write_le8(client, reg, addr << 1); | ||
154 | |||
155 | reg = pdata->dev_type == FPD3_SER_DEV ? | ||
156 | FPD3_SER_SLAVE_AL0 : FPD3_DES_SLAVE_AL0; | ||
157 | i2c_write_le8(client, reg, data->slave_alias[i] << 1); | ||
158 | |||
159 | return data->slave_alias[i]; | ||
160 | } else | ||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | static u8 __get_alias_addr(struct i2c_adapter *adap, u8 addr) | ||
165 | { | ||
166 | struct i2c_client *client = i2c_get_adapdata(adap); | ||
167 | struct fpd3_serdes_data *data = i2c_get_clientdata(client); | ||
168 | u8 new_alias; | ||
169 | int i; | ||
170 | |||
171 | /* master device should have the mapping between the | ||
172 | * slave address on remote bus to alias for which master device | ||
173 | * is monitoring for transactions */ | ||
174 | for (i = 0; i < data->num_slaves; i++) { | ||
175 | if (data->slave_addr[i] == addr) | ||
176 | break; | ||
177 | } | ||
178 | |||
179 | if (data->slave_addr[i] == addr) | ||
180 | return data->slave_alias[i]; | ||
181 | |||
182 | new_alias = fpd3_alloc_addr(adap, addr); | ||
183 | if (new_alias == 0) | ||
184 | dev_err(&adap->dev, "Cannot translate chip addr 0x%02x", addr); | ||
185 | |||
186 | return new_alias; | ||
187 | } | ||
188 | |||
189 | static struct i2c_adapter *__get_alias_adapter(struct i2c_adapter *adap) | ||
190 | { | ||
191 | struct i2c_client *client = i2c_get_adapdata(adap); | ||
192 | |||
193 | /* Same i2c adapter used for the master device should be | ||
194 | * used for communicating with the remote device via alias */ | ||
195 | return client->adapter; | ||
196 | } | ||
197 | |||
198 | static int fpd3_master_xfer(struct i2c_adapter *adap, | ||
199 | struct i2c_msg msgs[], int num) | ||
200 | { | ||
201 | struct i2c_adapter *alias_adap; | ||
202 | struct i2c_msg *new_msg; | ||
203 | u8 alias_addr; | ||
204 | int i, ret = 0; | ||
205 | |||
206 | if (setup_link(adap)) | ||
207 | return -EIO; | ||
208 | |||
209 | alias_adap = __get_alias_adapter(adap); | ||
210 | |||
211 | new_msg = kcalloc(num, sizeof(*new_msg), GFP_KERNEL); | ||
212 | |||
213 | for (i = 0; i < num; i++) { | ||
214 | alias_addr = __get_alias_addr(adap, msgs[i].addr); | ||
215 | if (alias_addr == 0) { | ||
216 | ret = -EINVAL; | ||
217 | goto cleanup; | ||
218 | } | ||
219 | |||
220 | /* Copy the i2c_msgs into temporary buffer; xlate address */ | ||
221 | new_msg[i] = msgs[i]; | ||
222 | new_msg[i].addr = alias_addr; | ||
223 | } | ||
224 | |||
225 | /* Issue the messages on the alias adapter */ | ||
226 | ret = i2c_transfer(alias_adap, new_msg, num); | ||
227 | |||
228 | cleanup: | ||
229 | kfree(new_msg); | ||
230 | |||
231 | return ret; | ||
232 | } | ||
233 | |||
234 | static int fpd3_smbus_xfer(struct i2c_adapter *adap, u16 addr, | ||
235 | unsigned short flags, char read_write, | ||
236 | u8 command, int size, union i2c_smbus_data *data) | ||
237 | { | ||
238 | struct i2c_adapter *alias_adap; | ||
239 | u8 alias_addr; | ||
240 | |||
241 | if (setup_link(adap)) | ||
242 | return -EIO; | ||
243 | |||
244 | alias_adap = __get_alias_adapter(adap); | ||
245 | alias_addr = __get_alias_addr(adap, addr); | ||
246 | if (alias_addr == 0) | ||
247 | return -EINVAL; | ||
248 | |||
249 | return i2c_smbus_xfer(alias_adap, alias_addr, flags, read_write, | ||
250 | command, size, data); | ||
251 | } | ||
252 | |||
253 | static u32 fpd3_i2c_func(struct i2c_adapter *adap) | ||
254 | { | ||
255 | return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK) | | ||
256 | I2C_FUNC_PROTOCOL_MANGLING; | ||
257 | } | ||
258 | |||
259 | static const struct i2c_algorithm fpd3_i2c_algo = { | ||
260 | .master_xfer = fpd3_master_xfer, | ||
261 | .smbus_xfer = fpd3_smbus_xfer, | ||
262 | .functionality = fpd3_i2c_func, | ||
263 | }; | ||
264 | |||
265 | static int parse_address_translation(struct i2c_client *client) | ||
266 | { | ||
267 | struct device_node *node = client->dev.of_node; | ||
268 | struct fpd3_serdes_data *data = i2c_get_clientdata(client); | ||
269 | const struct fpd3_serdes_platform_data *pdata = data->pdata; | ||
270 | unsigned int slave_bus_addr, master_bus_addr; | ||
271 | int ret, i; | ||
272 | |||
273 | for (i = 0; i < pdata->nslaves + 1; i++) { | ||
274 | |||
275 | ret = of_property_read_u32_index(node, "ranges", 2 * i, | ||
276 | &slave_bus_addr); | ||
277 | if (ret) | ||
278 | break; | ||
279 | ret = of_property_read_u32_index(node, "ranges", 2 * i + 1, | ||
280 | &master_bus_addr); | ||
281 | if (ret) | ||
282 | break; | ||
283 | |||
284 | data->slave_addr[i] = slave_bus_addr; | ||
285 | data->slave_alias[i] = master_bus_addr; | ||
286 | } | ||
287 | data->num_slaves = i; | ||
288 | ret = 0; | ||
289 | |||
290 | if (i == 0) { | ||
291 | dev_err(&client->dev, "Master mode device does not have slave address translation information"); | ||
292 | return -ENODEV; | ||
293 | } | ||
294 | return 0; | ||
295 | } | ||
296 | |||
297 | int fpd3_register_i2c_adapter(struct i2c_client *client) | ||
298 | { | ||
299 | struct fpd3_serdes_data *data = i2c_get_clientdata(client); | ||
300 | struct i2c_adapter *adap; | ||
301 | int ret = 0; | ||
302 | |||
303 | dev_dbg(&client->dev, "Registering i2c adapter"); | ||
304 | |||
305 | adap = kzalloc(sizeof(*adap), GFP_KERNEL); | ||
306 | if (adap == NULL) | ||
307 | return -ENOMEM; | ||
308 | |||
309 | data->adap = adap; | ||
310 | adap->nr = -1; | ||
311 | adap->owner = THIS_MODULE; | ||
312 | adap->class = I2C_CLASS_HWMON; | ||
313 | adap->algo = &fpd3_i2c_algo; | ||
314 | adap->dev.parent = &client->dev; | ||
315 | adap->dev.of_node = client->dev.of_node; | ||
316 | strlcpy(adap->name, "LVDS I2C adapter", sizeof(adap->name)); | ||
317 | |||
318 | ret = parse_address_translation(client); | ||
319 | if (ret) | ||
320 | return ret; | ||
321 | |||
322 | i2c_set_adapdata(adap, client); | ||
323 | return i2c_add_numbered_adapter(adap); | ||
324 | } | ||
325 | |||
diff --git a/drivers/video/serdes/fpd3_serdes.c b/drivers/video/serdes/fpd3_serdes.c new file mode 100644 index 000000000000..3598683a3d31 --- /dev/null +++ b/drivers/video/serdes/fpd3_serdes.c | |||
@@ -0,0 +1,456 @@ | |||
1 | /* | ||
2 | * fpd3_serdes.c | ||
3 | * | ||
4 | * lvds based serial link interface for onboard communication. | ||
5 | * Copyright (C) 2014-2015 Texas Instruments Incorporated - http://www.ti.com/ | ||
6 | * Authors: Nikhil Devshatwar <nikhil.nd@ti.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License version 2 as published by | ||
10 | * the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along with | ||
18 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | |||
21 | /* | ||
22 | * Datasheets:- | ||
23 | * DS90UB913aq/DS90UB914aq http://www.ti.com/lit/ds/snls443a/snls443a.pdf | ||
24 | * DS90UH925Q http://www.ti.com/lit/ds/symlink/ds90uh925q-q1.pdf | ||
25 | * DS90UH928Q http://www.ti.com/lit/ds/snls440a/snls440a.pdf | ||
26 | * DS90UB924Q http://www.ti.com/lit/ds/snls512/snls512.pdf | ||
27 | * DS90UB921Q http://www.ti.com/lit/ds/symlink/ds90ub921-q1.pdf | ||
28 | * | ||
29 | * Documentation:- | ||
30 | * -> Documentation/video-serdes.txt | ||
31 | * -> Documentation/devicetree/bindings/video/fpd3-serdes.txt | ||
32 | */ | ||
33 | |||
34 | #include <linux/kernel.h> | ||
35 | #include <linux/module.h> | ||
36 | #include <linux/slab.h> | ||
37 | #include <linux/i2c.h> | ||
38 | #include <linux/gpio.h> | ||
39 | #include <linux/delay.h> | ||
40 | #include <linux/of_gpio.h> | ||
41 | #include <linux/of_device.h> | ||
42 | #include "fpd3_serdes.h" | ||
43 | |||
44 | static const unsigned int fpd3_12bit_ser_init[] = { | ||
45 | /* auto volt ctrl en, 3.3V, digital reset0, digital reset1 */ | ||
46 | FPD3_SER_RESET, 0x33, | ||
47 | /* RX CRC check, TX parity en, i2c passthrough, rising edge pclk */ | ||
48 | FPD3_SER_CONFIG1, 0xc5, | ||
49 | /* GPIO0 - o/p LOW, GPIO0 - o/p HIGH */ | ||
50 | FPD3_SER_GPIO_01, 0x55, | ||
51 | }; | ||
52 | |||
53 | static const unsigned int fpd3_12bit_des_init[] = { | ||
54 | /* back channel en */ | ||
55 | FPD3_DES_RESET, 0x04, | ||
56 | /* RX parity check, TX CRC check, auto volt ctrl en | ||
57 | * i2c passthrough, auto ack WR, rising edge pclk */ | ||
58 | FPD3_DES_CONFIG1, 0xec, | ||
59 | }; | ||
60 | |||
61 | static const unsigned int fpd3_24bit_ser_init[] = { | ||
62 | /* digital reset1 */ | ||
63 | FPD3_SER_RESET, 0x02, | ||
64 | /* back chan en, auto ack WR, i2c passthrough, rising edge pclk */ | ||
65 | FPD3_SER_CONFIG1, 0xab, | ||
66 | /* failsafe low, LFMODE override, high freq*/ | ||
67 | FPD3_SER_CONFIG2, 0x8a, | ||
68 | /* RGB data, 24bit, i2s data forwarding */ | ||
69 | FPD3_SER_DATA_CTRL, 0x8a, | ||
70 | }; | ||
71 | |||
72 | static const unsigned int fpd3_24bit_des_init[] = { | ||
73 | /* digital reset1 */ | ||
74 | FPD3_DES_RESET, 0x02, | ||
75 | /* back channel en */ | ||
76 | FPD3_DES_RESET, 0x04, | ||
77 | /* auto clk en, LFMODE override, high freq */ | ||
78 | FPD3_DES_CONFIG0, 0x2a, | ||
79 | /* failsafe pull up, i2c passthrough, auto ack */ | ||
80 | FPD3_DES_CONFIG1, 0x4c, | ||
81 | }; | ||
82 | |||
83 | static const unsigned int fpd3_921_ser_init[] = { | ||
84 | /* Reset entire digital block except registers */ | ||
85 | FPD3_SER_RESET, 0x01, | ||
86 | /* back chan en, auto ack WR, i2c passthrough, rising edge pclk */ | ||
87 | FPD3_SER_CONFIG1, 0x8b, | ||
88 | }; | ||
89 | |||
90 | static const unsigned int fpd3_924_des_init[] = { | ||
91 | /* digital reset1 */ | ||
92 | FPD3_DES_RESET, 0x02, | ||
93 | /* back channel en */ | ||
94 | FPD3_DES_RESET, 0x04, | ||
95 | }; | ||
96 | |||
97 | static struct fpd3_serdes_platform_data fpd3_serdes_pdata[] = { | ||
98 | { | ||
99 | .name = "fpd3_12b_ser", | ||
100 | .dev_type = FPD3_SER_DEV, | ||
101 | .ngpio = 4, | ||
102 | .nslaves = 1, | ||
103 | .device_id = 0xb0, | ||
104 | .gpio_2reg = 2 * FPD3_SER_GPIO_01, | ||
105 | .init_seq = fpd3_12bit_ser_init, | ||
106 | .init_len = ARRAY_SIZE(fpd3_12bit_ser_init), | ||
107 | }, | ||
108 | { | ||
109 | .name = "fpd3_12b_des", | ||
110 | .dev_type = FPD3_DES_DEV, | ||
111 | .ngpio = 4, | ||
112 | .nslaves = 8, | ||
113 | .device_id = 0xc0, | ||
114 | .gpio_2reg = 2 * FPD3_DES_GPIO_01, | ||
115 | .init_seq = fpd3_12bit_des_init, | ||
116 | .init_len = ARRAY_SIZE(fpd3_12bit_des_init), | ||
117 | }, | ||
118 | { | ||
119 | .name = "fpd3_24b_ser", | ||
120 | .dev_type = FPD3_SER_DEV, | ||
121 | .ngpio = 4, | ||
122 | .nslaves = 1, | ||
123 | .device_id = 0x36, | ||
124 | .gpio_2reg = 2 * FPD3_SER_GPIO_01 + 1, | ||
125 | .init_seq = fpd3_24bit_ser_init, | ||
126 | .init_len = ARRAY_SIZE(fpd3_24bit_ser_init), | ||
127 | }, | ||
128 | { | ||
129 | .name = "fpd3_24b_des", | ||
130 | .dev_type = FPD3_DES_DEV, | ||
131 | .ngpio = 4, | ||
132 | .nslaves = 8, | ||
133 | .device_id = 0x58, | ||
134 | .gpio_2reg = 2 * FPD3_DES_GPIO_01 + 1, | ||
135 | .init_seq = fpd3_24bit_des_init, | ||
136 | .init_len = ARRAY_SIZE(fpd3_24bit_des_init), | ||
137 | }, | ||
138 | { | ||
139 | .name = "fpd3_924_des", | ||
140 | .dev_type = FPD3_DES_DEV, | ||
141 | .ngpio = 4, | ||
142 | .nslaves = 8, | ||
143 | .device_id = 0x58, | ||
144 | .gpio_2reg = 2 * FPD3_DES_GPIO_01 + 1, | ||
145 | .init_seq = fpd3_924_des_init, | ||
146 | .init_len = ARRAY_SIZE(fpd3_924_des_init), | ||
147 | }, | ||
148 | { | ||
149 | .name = "fpd3_921_ser", | ||
150 | .dev_type = FPD3_SER_DEV, | ||
151 | .ngpio = 4, | ||
152 | .nslaves = 1, | ||
153 | .device_id = 0x18, | ||
154 | .gpio_2reg = 2 * FPD3_SER_GPIO_01 + 1, | ||
155 | .init_seq = fpd3_921_ser_init, | ||
156 | .init_len = ARRAY_SIZE(fpd3_921_ser_init), | ||
157 | }, | ||
158 | }; | ||
159 | |||
160 | /* GPIO operations */ | ||
161 | static int __fpd3_serdes_dirval(struct gpio_chip *chip, | ||
162 | unsigned offset, int value, int shift) | ||
163 | { | ||
164 | struct fpd3_serdes_data *data = | ||
165 | container_of(chip, struct fpd3_serdes_data, chip); | ||
166 | const struct fpd3_serdes_platform_data *pdata = data->pdata; | ||
167 | struct i2c_client *client = data->client; | ||
168 | int reg, val = 0x00; | ||
169 | |||
170 | reg = (pdata->gpio_2reg + offset) / 2; | ||
171 | if ((pdata->gpio_2reg + offset) % 2) | ||
172 | shift += 4; | ||
173 | |||
174 | val = i2c_read_le8(client, reg); | ||
175 | |||
176 | if (value) | ||
177 | val |= 1 << shift; | ||
178 | else | ||
179 | val &= ~(1 << shift); | ||
180 | |||
181 | return i2c_write_le8(client, reg, val); | ||
182 | } | ||
183 | |||
184 | static int fpd3_serdes_input(struct gpio_chip *chip, unsigned offset) | ||
185 | { | ||
186 | return __fpd3_serdes_dirval(chip, offset, | ||
187 | GPIO_DIR_INPUT, GPIO_SHIFT_DIR); | ||
188 | } | ||
189 | static int fpd3_serdes_output(struct gpio_chip *chip, | ||
190 | unsigned offset, int value) | ||
191 | { | ||
192 | int ret; | ||
193 | |||
194 | ret = __fpd3_serdes_dirval(chip, offset, | ||
195 | GPIO_DIR_OUTPUT, GPIO_SHIFT_DIR); | ||
196 | |||
197 | if (ret) | ||
198 | ret = __fpd3_serdes_dirval(chip, offset, | ||
199 | value, GPIO_SHIFT_VAL); | ||
200 | |||
201 | return ret; | ||
202 | } | ||
203 | |||
204 | static void fpd3_serdes_set(struct gpio_chip *chip, unsigned offset, int value) | ||
205 | { | ||
206 | __fpd3_serdes_dirval(chip, offset, value, GPIO_SHIFT_VAL); | ||
207 | } | ||
208 | |||
209 | static int fpd3_serdes_get(struct gpio_chip *chip, unsigned offset) | ||
210 | { | ||
211 | struct fpd3_serdes_data *data = | ||
212 | container_of(chip, struct fpd3_serdes_data, chip); | ||
213 | const struct fpd3_serdes_platform_data *pdata = data->pdata; | ||
214 | struct i2c_client *client = data->client; | ||
215 | int reg; | ||
216 | |||
217 | int shift = GPIO_SHIFT_VAL; | ||
218 | reg = (pdata->gpio_2reg + offset) / 2; | ||
219 | if ((pdata->gpio_2reg + offset) % 2) | ||
220 | shift += 4; | ||
221 | |||
222 | return (i2c_read_le8(client, reg) | 1 << shift) ? 1 : 0; | ||
223 | } | ||
224 | |||
225 | static struct gpio_chip fpd3_serdes_gpiochip = { | ||
226 | .owner = THIS_MODULE, | ||
227 | .base = -1, | ||
228 | .ngpio = 4, | ||
229 | .can_sleep = false, | ||
230 | |||
231 | .get = fpd3_serdes_get, | ||
232 | .set = fpd3_serdes_set, | ||
233 | .direction_input = fpd3_serdes_input, | ||
234 | .direction_output = fpd3_serdes_output, | ||
235 | }; | ||
236 | |||
237 | int fpd3_serdes_initialize(struct i2c_client *client) | ||
238 | { | ||
239 | struct fpd3_serdes_data *data = i2c_get_clientdata(client); | ||
240 | const struct fpd3_serdes_platform_data *pdata = data->pdata; | ||
241 | const unsigned int *seq; | ||
242 | int i, len, reg, ret = 0, count = 0; | ||
243 | |||
244 | if (data->slave_mode == false) { | ||
245 | /* Wait for the device to initialize and show up device ID */ | ||
246 | reg = pdata->dev_type == FPD3_SER_DEV ? | ||
247 | FPD3_SER_DEV_ID : FPD3_SER_DEV_ID; | ||
248 | while (ret != pdata->device_id && count < FPD3_MAX_POLL_COUNT) { | ||
249 | ret = i2c_read_le8(client, reg); | ||
250 | count++; | ||
251 | mdelay(3); | ||
252 | } | ||
253 | if (count == FPD3_MAX_POLL_COUNT) { | ||
254 | dev_err(&client->dev, "Not a %s chip", pdata->name); | ||
255 | return -ENODEV; | ||
256 | } | ||
257 | } | ||
258 | |||
259 | len = pdata->init_len; | ||
260 | seq = pdata->init_seq; | ||
261 | for (i = 0; i < len; i += 2) { | ||
262 | ret = i2c_write_le8(client, seq[i], seq[i+1]); | ||
263 | if (ret) | ||
264 | break; | ||
265 | if (seq[i] == 0x01) | ||
266 | udelay(500); | ||
267 | else | ||
268 | udelay(10); | ||
269 | } | ||
270 | |||
271 | return ret; | ||
272 | } | ||
273 | EXPORT_SYMBOL(fpd3_serdes_initialize); | ||
274 | |||
275 | /* On Vision app board (up to Rev B), the deserializer I2C addresses | ||
276 | * conflicts with the HDMI receiver chip, making deserializer unaccessible. | ||
277 | * The workaround is to change the I2C address of the HDMI receiver at runtime. | ||
278 | * Following code removes the conflict between HDMI SIL9127 and deserializers | ||
279 | * 0x31 is default I2C address of SIL9127 | ||
280 | */ | ||
281 | static int fpd3_serdes_remove_conflict(struct i2c_client *client) | ||
282 | { | ||
283 | struct regval { | ||
284 | u8 reg; | ||
285 | u8 val; | ||
286 | } conflict_regval[] = { | ||
287 | { 0x14, 0xf4, }, | ||
288 | { 0x15, 0xf6, }, | ||
289 | { 0x16, 0xf8, }, | ||
290 | { 0x17, 0xfa, }, | ||
291 | { 0x18, 0xfc, }, | ||
292 | { 0x19, 0xfe, }, | ||
293 | }; | ||
294 | union i2c_smbus_data data; | ||
295 | int i, ret; | ||
296 | u16 addr = 0x31; | ||
297 | static bool conflict_exist = true; | ||
298 | |||
299 | if (!conflict_exist) | ||
300 | return 0; | ||
301 | |||
302 | conflict_exist = false; | ||
303 | for (i = 0; i < 6; i++) { | ||
304 | data.byte = conflict_regval[i].val; | ||
305 | ret = i2c_smbus_xfer(client->adapter, addr, client->flags, | ||
306 | I2C_SMBUS_WRITE, conflict_regval[i].reg, | ||
307 | I2C_SMBUS_BYTE_DATA, &data); | ||
308 | if (ret) | ||
309 | return ret; | ||
310 | } | ||
311 | |||
312 | dev_err(&client->dev, "Removed conflict b/w HDMI SIL"); | ||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | static int fpd3_serdes_of_probe(struct i2c_client *client, | ||
317 | struct device_node *node) | ||
318 | { | ||
319 | struct fpd3_serdes_data *data = i2c_get_clientdata(client); | ||
320 | int gpio, ret; | ||
321 | |||
322 | gpio = of_get_gpio(node, 0); | ||
323 | if (gpio_is_valid(gpio)) { | ||
324 | /* Toggle the pdb bit from LOW to HIGH */ | ||
325 | ret = devm_gpio_request_one(&client->dev, gpio, | ||
326 | GPIOF_INIT_HIGH, "des_pdb"); | ||
327 | } else if (gpio == -ENOENT) | ||
328 | /* Entry not present - no need to toggle pdb */ | ||
329 | ret = 0; | ||
330 | else | ||
331 | ret = gpio; | ||
332 | |||
333 | if (ret) | ||
334 | return ret; | ||
335 | |||
336 | data->gpio_export = of_find_property(node, "gpio-controller", NULL) ? | ||
337 | true : false; | ||
338 | data->slave_mode = of_find_property(node, "slave-mode", NULL) ? | ||
339 | true : false; | ||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | static const struct i2c_device_id fpd3_serdes_i2c_ids[] = { | ||
344 | { "ds90ub913aq", 8 }, | ||
345 | { "ds90ub914aq", 8 }, | ||
346 | { "ds90uh925q", 8 }, | ||
347 | { "ds90uh928q", 8 }, | ||
348 | { "ds90ub924q", 8 }, | ||
349 | { "ds90ub921q", 8 }, | ||
350 | { } | ||
351 | }; | ||
352 | MODULE_DEVICE_TABLE(i2c, fpd3_serdes_i2c_ids); | ||
353 | |||
354 | static const struct of_device_id fpd3_serdes_dt_ids[] = { | ||
355 | {.compatible = "ti,ds90ub913aq", &fpd3_serdes_pdata[0], }, | ||
356 | {.compatible = "ti,ds90ub914aq", &fpd3_serdes_pdata[1], }, | ||
357 | {.compatible = "ti,ds90uh925q", &fpd3_serdes_pdata[2], }, | ||
358 | {.compatible = "ti,ds90uh928q", &fpd3_serdes_pdata[3], }, | ||
359 | {.compatible = "ti,ds90ub924q", &fpd3_serdes_pdata[4], }, | ||
360 | {.compatible = "ti,ds90ub921q", &fpd3_serdes_pdata[5], }, | ||
361 | { } | ||
362 | }; | ||
363 | |||
364 | MODULE_DEVICE_TABLE(of, fpd3_serdes_dt_ids); | ||
365 | |||
366 | static int fpd3_serdes_probe(struct i2c_client *client, | ||
367 | const struct i2c_device_id *id) | ||
368 | { | ||
369 | const struct of_device_id *of_dev_id; | ||
370 | const struct fpd3_serdes_platform_data *pdata; | ||
371 | struct fpd3_serdes_data *data; | ||
372 | int status; | ||
373 | |||
374 | data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); | ||
375 | if (!data) | ||
376 | return -ENOMEM; | ||
377 | |||
378 | data->client = client; | ||
379 | i2c_set_clientdata(client, data); | ||
380 | |||
381 | fpd3_serdes_remove_conflict(client); | ||
382 | |||
383 | of_dev_id = of_match_device(fpd3_serdes_dt_ids, &client->dev); | ||
384 | if (!of_dev_id) { | ||
385 | dev_err(&client->dev, "Unable to match device"); | ||
386 | return -EINVAL; | ||
387 | } | ||
388 | pdata = of_dev_id->data; | ||
389 | data->pdata = pdata; | ||
390 | |||
391 | status = fpd3_serdes_of_probe(client, client->dev.of_node); | ||
392 | if (status) | ||
393 | goto fail; | ||
394 | |||
395 | if (data->slave_mode == false) { | ||
396 | status = fpd3_register_i2c_adapter(client); | ||
397 | if (status) { | ||
398 | dev_err(&client->dev, "Cannot register i2c adapter"); | ||
399 | goto fail; | ||
400 | } | ||
401 | } else { | ||
402 | status = fpd3_serdes_initialize(client); | ||
403 | if (status) | ||
404 | goto fail; | ||
405 | } | ||
406 | |||
407 | if (data->gpio_export == true) { | ||
408 | /* Register local gpios as a separate gpiochip */ | ||
409 | data->chip = fpd3_serdes_gpiochip; | ||
410 | data->chip.ngpio = pdata->ngpio; | ||
411 | data->chip.dev = &client->dev; | ||
412 | data->chip.label = client->name; | ||
413 | status = gpiochip_add(&data->chip); | ||
414 | if (status) | ||
415 | goto fail; | ||
416 | } | ||
417 | |||
418 | if (status) | ||
419 | goto unreg_gpio; | ||
420 | |||
421 | dev_err(&client->dev, "%s %s ready", pdata->dev_type == FPD3_SER_DEV ? | ||
422 | "Serializer" : "Deserializer", data->pdata->name); | ||
423 | |||
424 | return 0; | ||
425 | |||
426 | unreg_gpio: | ||
427 | if (data->gpio_export == true) { | ||
428 | gpiochip_remove(&data->chip); | ||
429 | return -1; | ||
430 | } | ||
431 | fail: | ||
432 | return status; | ||
433 | } | ||
434 | |||
435 | static int fpd3_serdes_remove(struct i2c_client *client) | ||
436 | { | ||
437 | struct fpd3_serdes_data *data = i2c_get_clientdata(client); | ||
438 | kfree(data); | ||
439 | |||
440 | return 0; | ||
441 | } | ||
442 | |||
443 | static struct i2c_driver fpd3_serdes_driver = { | ||
444 | .driver = { | ||
445 | .name = "fpd3_serdes", | ||
446 | .owner = THIS_MODULE, | ||
447 | .of_match_table = fpd3_serdes_dt_ids, | ||
448 | }, | ||
449 | .probe = fpd3_serdes_probe, | ||
450 | .remove = fpd3_serdes_remove, | ||
451 | .id_table = fpd3_serdes_i2c_ids | ||
452 | }; | ||
453 | module_i2c_driver(fpd3_serdes_driver); | ||
454 | |||
455 | MODULE_LICENSE("GPL"); | ||
456 | MODULE_AUTHOR("Nikhil Devshatwar"); | ||
diff --git a/drivers/video/serdes/fpd3_serdes.h b/drivers/video/serdes/fpd3_serdes.h new file mode 100644 index 000000000000..45c695ab27da --- /dev/null +++ b/drivers/video/serdes/fpd3_serdes.h | |||
@@ -0,0 +1,108 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/i2c.h> | ||
3 | #include <linux/gpio.h> | ||
4 | |||
5 | /* Deserializer registers */ | ||
6 | #define FPD3_DES_DEV_ID 0x00 | ||
7 | #define FPD3_DES_RESET 0x01 | ||
8 | #define FPD3_DES_CONFIG0 0x02 | ||
9 | #define FPD3_DES_CONFIG1 0x03 | ||
10 | |||
11 | #define FPD3_DES_SER_ID 0x06 | ||
12 | #define FPD3_DES_SER_AL 0x07 | ||
13 | #define FPD3_DES_SLAVE_ID0 0x08 | ||
14 | #define FPD3_DES_SLAVE_AL0 0x10 | ||
15 | |||
16 | #define FPD3_DES_GN_STS 0x1c | ||
17 | #define FPD3_DES_GPIO_01 0x1d | ||
18 | #define FPD3_DES_GPIO_23 0x1e | ||
19 | |||
20 | #define FPD3_DES_I2C_CTRL1 0x21 | ||
21 | #define FPD3_DES_I2C_CTRL2 0x22 | ||
22 | |||
23 | /* Serializer registers */ | ||
24 | #define FPD3_SER_DEV_ID 0x00 | ||
25 | #define FPD3_SER_RESET 0x01 | ||
26 | #define FPD3_SER_CONFIG0 0x02 | ||
27 | #define FPD3_SER_CONFIG1 0x03 | ||
28 | #define FPD3_SER_CONFIG2 0x04 | ||
29 | |||
30 | #define FPD3_SER_DES_ID 0x06 | ||
31 | #define FPD3_SER_DES_AL 0x06 | ||
32 | #define FPD3_SER_SLAVE_ID0 0x07 | ||
33 | #define FPD3_SER_SLAVE_AL0 0x08 | ||
34 | |||
35 | #define FPD3_SER_GN_STS 0x0c | ||
36 | #define FPD3_SER_GPIO_01 0x0d | ||
37 | #define FPD3_SER_GPIO_23 0x0e | ||
38 | |||
39 | #define FPD3_SER_DATA_CTRL 0x12 | ||
40 | #define FPD3_SER_I2C_CTRL1 0x21 | ||
41 | #define FPD3_SER_I2C_CTRL2 0x22 | ||
42 | |||
43 | /* Generic macros */ | ||
44 | #define GPIO_SHIFT_DIR 3 | ||
45 | #define GPIO_SHIFT_VAL 1 | ||
46 | #define GPIO_DIR_INPUT 1 | ||
47 | #define GPIO_DIR_OUTPUT 0 | ||
48 | |||
49 | #define SIGNAL_DETECT (1<<0) | ||
50 | |||
51 | #define FPD3_MAX_POLL_COUNT 100 | ||
52 | #define FPD3_SERDES_MAX_SLAVES 10 | ||
53 | |||
54 | enum fpd3_device_type { | ||
55 | FPD3_SER_DEV, | ||
56 | FPD3_DES_DEV, | ||
57 | }; | ||
58 | |||
59 | struct fpd3_serdes_data { | ||
60 | struct i2c_client *client; | ||
61 | bool slave_mode; | ||
62 | |||
63 | struct gpio_chip chip; | ||
64 | bool gpio_export; | ||
65 | |||
66 | struct i2c_adapter *adap; | ||
67 | unsigned int slave_addr[FPD3_SERDES_MAX_SLAVES]; | ||
68 | unsigned int slave_alias[FPD3_SERDES_MAX_SLAVES]; | ||
69 | const char *slave_name[FPD3_SERDES_MAX_SLAVES]; | ||
70 | int num_slaves; | ||
71 | int link_ok; | ||
72 | |||
73 | const struct fpd3_serdes_platform_data *pdata; | ||
74 | }; | ||
75 | |||
76 | struct fpd3_serdes_platform_data { | ||
77 | char *name; | ||
78 | enum fpd3_device_type dev_type; | ||
79 | int device_id; | ||
80 | int ngpio; | ||
81 | int nslaves; | ||
82 | int gpio_2reg; | ||
83 | const unsigned int *init_seq; | ||
84 | int init_len; | ||
85 | }; | ||
86 | |||
87 | static inline int i2c_write_le8(struct i2c_client *client, unsigned addr, | ||
88 | unsigned data) | ||
89 | { | ||
90 | int ret = i2c_smbus_write_byte_data(client, addr, data); | ||
91 | if (ret) | ||
92 | dev_dbg(&client->dev, "Failed to write 0x%02x to 0x%02x", | ||
93 | data, addr); | ||
94 | return ret; | ||
95 | } | ||
96 | |||
97 | static inline int i2c_read_le8(struct i2c_client *client, unsigned addr) | ||
98 | { | ||
99 | int ret = (int)i2c_smbus_read_byte_data(client, addr); | ||
100 | if (ret < 0) | ||
101 | dev_dbg(&client->dev, "Failed to read 0x%02x, Error = %d", | ||
102 | addr, ret); | ||
103 | return ret; | ||
104 | } | ||
105 | |||
106 | int fpd3_register_i2c_adapter(struct i2c_client *client); | ||
107 | int fpd3_serdes_initialize(struct i2c_client *client); | ||
108 | |||
diff --git a/firmware/Makefile b/firmware/Makefile index e297e1b52636..d019ab46c2cd 100644 --- a/firmware/Makefile +++ b/firmware/Makefile | |||
@@ -96,6 +96,9 @@ fw-shipped-$(CONFIG_SND_WAVEFRONT) += yamaha/yss225_registers.bin | |||
96 | fw-shipped-$(CONFIG_TEHUTI) += tehuti/bdx.bin | 96 | fw-shipped-$(CONFIG_TEHUTI) += tehuti/bdx.bin |
97 | fw-shipped-$(CONFIG_TIGON3) += tigon/tg3.bin tigon/tg3_tso.bin \ | 97 | fw-shipped-$(CONFIG_TIGON3) += tigon/tg3.bin tigon/tg3_tso.bin \ |
98 | tigon/tg3_tso5.bin | 98 | tigon/tg3_tso5.bin |
99 | |||
100 | fw-shipped-$(CONFIG_VIDEO_TI_VPDMA_LOAD_FW) += vpdma-1b8.bin | ||
101 | |||
99 | fw-shipped-$(CONFIG_TYPHOON) += 3com/typhoon.bin | 102 | fw-shipped-$(CONFIG_TYPHOON) += 3com/typhoon.bin |
100 | fw-shipped-$(CONFIG_USB_EMI26) += emi26/loader.fw emi26/firmware.fw \ | 103 | fw-shipped-$(CONFIG_USB_EMI26) += emi26/loader.fw emi26/firmware.fw \ |
101 | emi26/bitstream.fw | 104 | emi26/bitstream.fw |
diff --git a/firmware/vpdma-1b8.bin.ihex b/firmware/vpdma-1b8.bin.ihex new file mode 100644 index 000000000000..ddf307dd3e29 --- /dev/null +++ b/firmware/vpdma-1b8.bin.ihex | |||
@@ -0,0 +1,252 @@ | |||
1 | :10000000064B408007680749064A005102441F0812 | ||
2 | :10001000064A003102441E080449418004484080D9 | ||
3 | :100020000680000C01D002C01681010000441C08AB | ||
4 | :1000300001441D080649E809064818080185064AD2 | ||
5 | :1000400001002181219400441B080044180806483F | ||
6 | :10005000010000441A080648001C0044190806491B | ||
7 | :1000600000000144250801442408064818080144FA | ||
8 | :100070002108004420080648E809068001000144E0 | ||
9 | :100080002308004422080144260806480080004452 | ||
10 | :100090002708064834000044428006480000004417 | ||
11 | :1000A000F880064801000044F980064B1808864B8A | ||
12 | :1000B000200807BC0FB80004064801000044FF8078 | ||
13 | :1000C0000648FFFF0044F8800648FFFF0044F9801F | ||
14 | :1000D000064800000044580800445D0800445E08DB | ||
15 | :1000E00000445F0800445C08004457090044590973 | ||
16 | :1000F00000445A0900445B0900445C0900445D095E | ||
17 | :1001000000445E0900445F09004460090044660938 | ||
18 | :10011000004465090648D1000044E18006486A02AF | ||
19 | :100120000044E2800648F9050044E3800648B8012F | ||
20 | :100130000044FC800044FE800004064800000044A7 | ||
21 | :10014000540900445509004456090448FE8006AA93 | ||
22 | :1001500008000649010001940044FF80864B5909BC | ||
23 | :10016000C483FE800F480ECC064B01800648080071 | ||
24 | :1001700004A8FE80308307480689F0011685F00147 | ||
25 | :1001800001C881450649FF010144FD800FB90649B8 | ||
26 | :1001900042802183074A26867F00CCCC0448E08039 | ||
27 | :1001A00000E00648FFFF0044F880064B59093483FD | ||
28 | :1001B000FE80064A00000245044AFE8002446108AF | ||
29 | :1001C00026A9050001446808064B32081383074836 | ||
30 | :1001D0000044630826A9080001446708064B4080D4 | ||
31 | :1001E000138307680044650807480044660836839F | ||
32 | :1001F000030007480680F9FF03CC064AD70502E052 | ||
33 | :100200000648000000446408064B300826A9050093 | ||
34 | :100210001383076800445D0800445C080045064BF2 | ||
35 | :1002200033081383074800445F080648510100E083 | ||
36 | :1002300004486708064B43803083074932CC044AA0 | ||
37 | :10024000FE80064B6709238306481F010045864B45 | ||
38 | :100250004280C48367080F4836830800004506487B | ||
39 | :100260007F008045064B0180348367080648FFFF06 | ||
40 | :1002700000450448540912C806488001044955093C | ||
41 | :10028000018C0045068C80000044FC80064B34083D | ||
42 | :1002900026AA05003283064800000045064897015B | ||
43 | :1002A00000E0044AFE80064B6709238306481801D4 | ||
44 | :1002B0000045044AFE8006490800064B018012AA48 | ||
45 | :1002C0002383064801010045864B0F080F4A0DD8CD | ||
46 | :1002D000064800010045864B07080F4A06D8064825 | ||
47 | :1002E000FA0100450044FF8025C00448FE8006A8AE | ||
48 | :1002F0000500064B34080383044964080145064B96 | ||
49 | :100300003108038304495D08014506480080004424 | ||
50 | :10031000FA80064A000002449108044AFE80064B17 | ||
51 | :100320006709238306481801068C008000450648AB | ||
52 | :100330009A0000E00649005106480001108C004474 | ||
53 | :100340001F08044A660802441D080244D18004497B | ||
54 | :10035000650801441C080144D08004486308064B2A | ||
55 | :100360004380348367080749018603D80244620842 | ||
56 | :1003700006C016800000064A00000244620804829B | ||
57 | :10038000640802446408044A640806A81000004493 | ||
58 | :100390001B08004418080044D280064801000044AD | ||
59 | :1003A000D380064A000004495C0802442508014441 | ||
60 | :1003B00024080449910807C806490000014491082F | ||
61 | :1003C00004495C0805C00449920802CC04495D0850 | ||
62 | :1003D0000244210801442008064900000144920813 | ||
63 | :1003E00004495F0802442308014422080244260805 | ||
64 | :1003F0000649008001442708864B18080FBE0448B0 | ||
65 | :100400006208064B4380348367080045864B20080A | ||
66 | :100410000448D480004465080448D5800044660838 | ||
67 | :100420000FB806483400064B42800449670813831E | ||
68 | :100430000045044AFE80064B6709238306491801DC | ||
69 | :10044000168D0040014536830800004536830800BC | ||
70 | :1004500004485D080045064B43803483670807491C | ||
71 | :100460000448FE80064B6709038336831800014564 | ||
72 | :1004700004496708064B40801383044865080065FB | ||
73 | :100480000448660800450448FE8006A80500064B9F | ||
74 | :1004900034080383044964080145064B310803838B | ||
75 | :1004A00004495D0801450648970100E006480080C0 | ||
76 | :1004B0000044FA80044AFE80064B670923830648FD | ||
77 | :1004C0001801068C00C0004506489A0000E0004470 | ||
78 | :1004D000EE8000E4044AFE80064B018026A9080055 | ||
79 | :1004E00001446708064B4080138307680044650891 | ||
80 | :1004F0000768004466080768076800446208074800 | ||
81 | :10050000004460080244610826AA05000244680805 | ||
82 | :10051000064B30082383076800445C0807680044E2 | ||
83 | :100520005D08076800445E08076800445F080748E4 | ||
84 | :1005300000446408004463080448640807CC044885 | ||
85 | :100540005E08004463080648180100E0044B5D089B | ||
86 | :100550000649F5FF368307000748109406490A004C | ||
87 | :1005600010840CC80649010010840BC8108403C80D | ||
88 | :100570000648C40200E006488E0400E00648DC029B | ||
89 | :1005800000E00648CC0300E036830800044A5D081A | ||
90 | :10059000024536830800044A640802450448FE8088 | ||
91 | :1005A00006490800864B018010A888830648FB0195 | ||
92 | :1005B000804506489A0000E0044A640806CC0648D4 | ||
93 | :1005C0008A0300E006487C0300E0044A64082680B1 | ||
94 | :1005D000FFFFF8C8044B5D08B68306000F48068885 | ||
95 | :1005E000004000448F080F480688008000445409EA | ||
96 | :1005F000B68307000F480688FF01044AFE800649BB | ||
97 | :100600000800864B018012AAA88380450649030092 | ||
98 | :100610009097C68307000F4A05D8B68306000F4A95 | ||
99 | :1006200004D808C006489B0300E09097C6830200E8 | ||
100 | :100630000F49F8D8044AFE80864B0180064908001D | ||
101 | :1006400012AAA8830649FE0181450144FF8007BD27 | ||
102 | :10065000064903009097C68302000F49168D00805B | ||
103 | :10066000814536830800044954090DC80649030032 | ||
104 | :100670009097C68307000F491689008004488F08A9 | ||
105 | :10068000108D01448F0806480100044A5609209441 | ||
106 | :10069000044A5509028E02445509044A5F0823851D | ||
107 | :1006A00004D8044B5C0803445D0804498F0805C85E | ||
108 | :1006B00007B81689000001448F0807B83683080080 | ||
109 | :1006C00006480100044A56092681010001445609E2 | ||
110 | :1006D000044964081681FEFF0144640823C8044AE3 | ||
111 | :1006E0005F08328505D803445D080648A60200E08D | ||
112 | :1006F00004485C0800445D0804485D0804495F083C | ||
113 | :100700000680080000449208108404D806480100BE | ||
114 | :100710000044910804485E080649FFFF1094004415 | ||
115 | :10072000630834C004485C0800445D0804485E085F | ||
116 | :10073000004463082BC0B68306000F4801D810C0E0 | ||
117 | :10074000044AFE80864B01800649080012AAA8834D | ||
118 | :100750000648FE0180450044FF8036831000B0C08B | ||
119 | :1007600004486808064B34080383044964080145BB | ||
120 | :10077000064B3108038304495D0801450AC0064859 | ||
121 | :10078000100000448E080648670200E00648180181 | ||
122 | :1007900000E006489A0000E0044A640803CC0648DA | ||
123 | :1007A000500400E0044B5D08B68306000F4869C89A | ||
124 | :1007B000064A000004495C08024425080144240854 | ||
125 | :1007C00004495D08024421080144200804495F08E7 | ||
126 | :1007D00002442308014422080244260806490080F6 | ||
127 | :1007E00001442708044AFE8006490800064B0180A0 | ||
128 | :1007F00012AA238306480101064900800045864B62 | ||
129 | :100800000F080F4A59D80648000106490040004524 | ||
130 | :10081000864B07080F4A50D8064901010144FD8064 | ||
131 | :100820000044FF800648FC010045044B5D0807BCFE | ||
132 | :10083000B68306000F680F49168AFF011689000467 | ||
133 | :1008400003C80680010002C006480100864B4280B2 | ||
134 | :10085000C483670806493E00218181450449640834 | ||
135 | :1008600001850144640806A80800308202445D083E | ||
136 | :10087000064B2008864B080807B90F490F490F4956 | ||
137 | :100880000AC004485D08068008000449640816810F | ||
138 | :10089000FFFF06C834C004495F08218526D814C06C | ||
139 | :1008A0000144640804495E08064AFFFF2196024499 | ||
140 | :1008B00063080648180100E0064800800044FA80FA | ||
141 | :1008C0000648FF800044F98004486808064B340855 | ||
142 | :1008D0000383044964080145064B31080383044936 | ||
143 | :1008E0005D08014506489A0000E004485C080044A1 | ||
144 | :1008F0005D08044A5E0804496408D2C8E5C0064B96 | ||
145 | :10090000310834836808004500445D0836830300DD | ||
146 | :100910000145014464080648A60200E0044AFE803E | ||
147 | :10092000044B5D0836830600074806880F000BC895 | ||
148 | :1009300006490100108421C810842DC810843BC8CA | ||
149 | :1009400010843FC87BC036830100044AFE800748FC | ||
150 | :100950000688FF01864B9308C6830100C0830F49B8 | ||
151 | :10096000068C00800044FD8007B8864B4280064814 | ||
152 | :10097000080002AAA88381456FC0044AFE80064988 | ||
153 | :100980000800864BF080A88336830100074806885C | ||
154 | :10099000FF01804561C0044AFE8006490800864B7D | ||
155 | :1009A000428012A9C183138307480688FF0126826B | ||
156 | :1009B0004700824551C03683FAFF07480044FB8058 | ||
157 | :1009C0004BC0044AFE8006490800864B018012AAEB | ||
158 | :1009D000A8833683010007480688FF01804506ABDF | ||
159 | :1009E00008003683070007491689008009CC368342 | ||
160 | :1009F000FCFF0749168A008008C8168A004005CC0B | ||
161 | :100A000004485D080449640832C00648FE01804578 | ||
162 | :100A10000044FF80044B5D083683080076C03683AF | ||
163 | :100A2000010007480688FF01068C00803683F9FF25 | ||
164 | :100A30000044FD8007B83683080067C01084EFC803 | ||
165 | :100A4000108418C8108422C810843EC8108453C86B | ||
166 | :100A50001084064AC90502E004485D0806800800C3 | ||
167 | :100A6000044964081681FFFF04865F0863D8064ABC | ||
168 | :100A7000BE0502E00649FCFF3683010007680688D0 | ||
169 | :100A8000FF010044EE800648850500E0064A0000AC | ||
170 | :100A900002449108044AFE8006490800864B4080C3 | ||
171 | :100AA00012AAA883064806000387076880650768BE | ||
172 | :100AB0008065C683010007488045064A000002445D | ||
173 | :100AC00064080648DC0000E0076907490648FF01A2 | ||
174 | :100AD000108906480000864B7E0880658165806528 | ||
175 | :100AE00080658065806580658065864B7E080FBC6B | ||
176 | :100AF000368301000AC03683FEFF07480688FF01DF | ||
177 | :100B00000044FA803683040000C00448640806806C | ||
178 | :100B1000FFFF15C80044640804495F0803445D08EA | ||
179 | :100B2000318403D80648A60200E004485C0800446B | ||
180 | :100B30005D08F8C004485C0800445D081FC0044814 | ||
181 | :100B40005E080044630804495F0803445D0831847B | ||
182 | :100B500003D80648180100E004485C0800445D081A | ||
183 | :100B60000648180100E004485C0800445D08044899 | ||
184 | :100B70005E080044630806489A0000E0064B31080E | ||
185 | :100B800034836808004536830300014506489A000F | ||
186 | :100B900000E00448FE8006490800864B018010A84A | ||
187 | :100BA00088830648FD01804506489A0000E0044A13 | ||
188 | :100BB0006708064B4080328307680649FFFF90971D | ||
189 | :100BC000074A268A010002C8C68F00800F4A06889D | ||
190 | :100BD000010003C80649F8FF12960448FE80064942 | ||
191 | :100BE0000800864B018010A888838245064A9A0037 | ||
192 | :100BF00002E006489A0000E000000000000000004B | ||
193 | :100C00000000001C01001000020000000031005133 | ||
194 | :100C100000000000000000000000000000000000D4 | ||
195 | :100C200000000000000000000000000000000000C4 | ||
196 | :100C3000001000104000FF110000001200124000E0 | ||
197 | :100C4000FF130000001400144000FF150000001600 | ||
198 | :100C500000164000FF170000001800184000FF19A0 | ||
199 | :100C60000000001A001A4000FF1B0000001C001CBE | ||
200 | :100C70004000FF1D0000001E001E4000FF1F00007E | ||
201 | :100C80000000000000000000000000000000000064 | ||
202 | :100C90000000000000000000000000000000000054 | ||
203 | :100CA0000000000000000000000000000000000044 | ||
204 | :100CB0000000000000000000000000000000000034 | ||
205 | :100CC0000000000000000000000000000000000420 | ||
206 | :100CD0000000000000000000000000000000000014 | ||
207 | :100CE0000000000000000000000000000000000004 | ||
208 | :100CF000000000000000000D0100000002000300E1 | ||
209 | :100D00000400050006000700080009000A000B00A7 | ||
210 | :100D10000C000D000E000F00100011001400130055 | ||
211 | :100D2000150016001700180019001A001B001C00FF | ||
212 | :100D30001D001F00200021002A002B002C002A008B | ||
213 | :100D40002B002C0022002200220022002200220080 | ||
214 | :100D50002200220022002200220022002200220083 | ||
215 | :100D6000220022002300230023002300230023006D | ||
216 | :100D7000230023002300230023002300230023005B | ||
217 | :100D8000230023003A003A003A003A003A003A00C1 | ||
218 | :100D90003A003A003A003A003A003A003A003A0083 | ||
219 | :100DA0003A003A003B003B003B003B003B003B006D | ||
220 | :100DB0003B003B003B003B003B003B003B003B005B | ||
221 | :100DC0003B003B00240025002200230024002200D9 | ||
222 | :100DD00026002600260026002600260026002600E3 | ||
223 | :100DE00026002600260026002600260026002600D3 | ||
224 | :100DF00027002700270027002700270027002700BB | ||
225 | :100E000027002700270027002700270027002700AA | ||
226 | :100E10003C003C003C003C003C003C003C003C00F2 | ||
227 | :100E20003C003C003C003C003C003C003C003C00E2 | ||
228 | :100E30003D003D003D003D003D003D003D003D00CA | ||
229 | :100E40003D003D003D003D003D003D003D003D00BA | ||
230 | :100E50002800290026002700280026002D00300049 | ||
231 | :100E600031002E002F0032003300350012001E002A | ||
232 | :100E70003700360039003800000000000000000094 | ||
233 | :100E80000000000000000000000000000000000062 | ||
234 | :100E90000000000000000000000000000000000052 | ||
235 | :100EA0000000000000000000000000000000000042 | ||
236 | :100EB0000000000000000000000000000000000032 | ||
237 | :100EC0000000000000000000000000000000000022 | ||
238 | :100ED0000000000000000000000000000000000012 | ||
239 | :100EE0000000000000000000000000000000000002 | ||
240 | :100EF00000000000000000000000000000000000F2 | ||
241 | :100F000000000000000000000000000000000000E1 | ||
242 | :100F100000000000000000000000000000000000D1 | ||
243 | :100F200000000000000000000000000000000000C1 | ||
244 | :100F300000000000000000000000000000000000B1 | ||
245 | :100F400000000000000000000000000000000000A1 | ||
246 | :100F50000000000000000000000000000000000091 | ||
247 | :100F60000000000000000000000000000000000081 | ||
248 | :100F70000000000000000000000000000000000071 | ||
249 | :100F80000000000000000000000000000000000061 | ||
250 | :100F90000000000000000000000000000000000051 | ||
251 | :020FA00000004F | ||
252 | :00000001FF | ||
diff --git a/include/asm-generic/dma-coherent.h b/include/asm-generic/dma-coherent.h index 0297e5875798..70d699e671a4 100644 --- a/include/asm-generic/dma-coherent.h +++ b/include/asm-generic/dma-coherent.h | |||
@@ -8,6 +8,11 @@ | |||
8 | */ | 8 | */ |
9 | int dma_alloc_from_coherent(struct device *dev, ssize_t size, | 9 | int dma_alloc_from_coherent(struct device *dev, ssize_t size, |
10 | dma_addr_t *dma_handle, void **ret); | 10 | dma_addr_t *dma_handle, void **ret); |
11 | |||
12 | int dma_malloc_from_coherent(struct device *dev, ssize_t size, | ||
13 | dma_addr_t *dma_handle, void **ret, | ||
14 | bool zero); | ||
15 | |||
11 | int dma_release_from_coherent(struct device *dev, int order, void *vaddr); | 16 | int dma_release_from_coherent(struct device *dev, int order, void *vaddr); |
12 | 17 | ||
13 | int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma, | 18 | int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma, |
@@ -25,6 +30,7 @@ void *dma_mark_declared_memory_occupied(struct device *dev, | |||
25 | dma_addr_t device_addr, size_t size); | 30 | dma_addr_t device_addr, size_t size); |
26 | #else | 31 | #else |
27 | #define dma_alloc_from_coherent(dev, size, handle, ret) (0) | 32 | #define dma_alloc_from_coherent(dev, size, handle, ret) (0) |
33 | #define dma_malloc_from_coherent(dev, size, handle, ret, zero) (0) | ||
28 | #define dma_release_from_coherent(dev, order, vaddr) (0) | 34 | #define dma_release_from_coherent(dev, order, vaddr) (0) |
29 | #define dma_mmap_from_coherent(dev, vma, vaddr, order, ret) (0) | 35 | #define dma_mmap_from_coherent(dev, vma, vaddr, order, ret) (0) |
30 | #endif | 36 | #endif |
diff --git a/include/asm-generic/dma-mapping-common.h b/include/asm-generic/dma-mapping-common.h index b1bc954eccf3..c987c61e2d05 100644 --- a/include/asm-generic/dma-mapping-common.h +++ b/include/asm-generic/dma-mapping-common.h | |||
@@ -242,16 +242,16 @@ dma_get_sgtable_attrs(struct device *dev, struct sg_table *sgt, void *cpu_addr, | |||
242 | #define arch_dma_alloc_attrs(dev, flag) (true) | 242 | #define arch_dma_alloc_attrs(dev, flag) (true) |
243 | #endif | 243 | #endif |
244 | 244 | ||
245 | static inline void *dma_alloc_attrs(struct device *dev, size_t size, | 245 | static inline void *dma_malloc_attrs(struct device *dev, size_t size, |
246 | dma_addr_t *dma_handle, gfp_t flag, | 246 | dma_addr_t *dma_handle, gfp_t flag, |
247 | struct dma_attrs *attrs) | 247 | struct dma_attrs *attrs, bool zero) |
248 | { | 248 | { |
249 | struct dma_map_ops *ops = get_dma_ops(dev); | 249 | struct dma_map_ops *ops = get_dma_ops(dev); |
250 | void *cpu_addr; | 250 | void *cpu_addr; |
251 | 251 | ||
252 | BUG_ON(!ops); | 252 | BUG_ON(!ops); |
253 | 253 | ||
254 | if (dma_alloc_from_coherent(dev, size, dma_handle, &cpu_addr)) | 254 | if (dma_malloc_from_coherent(dev, size, dma_handle, &cpu_addr, zero)) |
255 | return cpu_addr; | 255 | return cpu_addr; |
256 | 256 | ||
257 | if (!arch_dma_alloc_attrs(&dev, &flag)) | 257 | if (!arch_dma_alloc_attrs(&dev, &flag)) |
@@ -264,6 +264,13 @@ static inline void *dma_alloc_attrs(struct device *dev, size_t size, | |||
264 | return cpu_addr; | 264 | return cpu_addr; |
265 | } | 265 | } |
266 | 266 | ||
267 | static inline void *dma_alloc_attrs(struct device *dev, size_t size, | ||
268 | dma_addr_t *dma_handle, gfp_t flag, | ||
269 | struct dma_attrs *attrs) | ||
270 | { | ||
271 | return dma_malloc_attrs(dev, size, dma_handle, flag, attrs, true); | ||
272 | } | ||
273 | |||
267 | static inline void dma_free_attrs(struct device *dev, size_t size, | 274 | static inline void dma_free_attrs(struct device *dev, size_t size, |
268 | void *cpu_addr, dma_addr_t dma_handle, | 275 | void *cpu_addr, dma_addr_t dma_handle, |
269 | struct dma_attrs *attrs) | 276 | struct dma_attrs *attrs) |
@@ -283,6 +290,12 @@ static inline void dma_free_attrs(struct device *dev, size_t size, | |||
283 | ops->free(dev, size, cpu_addr, dma_handle, attrs); | 290 | ops->free(dev, size, cpu_addr, dma_handle, attrs); |
284 | } | 291 | } |
285 | 292 | ||
293 | static inline void *dma_malloc_coherent(struct device *dev, size_t size, | ||
294 | dma_addr_t *dma_handle, gfp_t flag) | ||
295 | { | ||
296 | return dma_malloc_attrs(dev, size, dma_handle, flag, NULL, false); | ||
297 | } | ||
298 | |||
286 | static inline void *dma_alloc_coherent(struct device *dev, size_t size, | 299 | static inline void *dma_alloc_coherent(struct device *dev, size_t size, |
287 | dma_addr_t *dma_handle, gfp_t flag) | 300 | dma_addr_t *dma_handle, gfp_t flag) |
288 | { | 301 | { |
diff --git a/include/linux/hwspinlock.h b/include/linux/hwspinlock.h index 859d673d98c8..b32e4898710f 100644 --- a/include/linux/hwspinlock.h +++ b/include/linux/hwspinlock.h | |||
@@ -24,6 +24,7 @@ | |||
24 | /* hwspinlock mode argument */ | 24 | /* hwspinlock mode argument */ |
25 | #define HWLOCK_IRQSTATE 0x01 /* Disable interrupts, save state */ | 25 | #define HWLOCK_IRQSTATE 0x01 /* Disable interrupts, save state */ |
26 | #define HWLOCK_IRQ 0x02 /* Disable interrupts, don't save state */ | 26 | #define HWLOCK_IRQ 0x02 /* Disable interrupts, don't save state */ |
27 | #define HWLOCK_MUTEX 0x03 /* Use a mutex for contexts that sleep */ | ||
27 | 28 | ||
28 | struct device; | 29 | struct device; |
29 | struct device_node; | 30 | struct device_node; |
@@ -242,6 +243,12 @@ int hwspin_lock_timeout_irq(struct hwspinlock *hwlock, unsigned int to) | |||
242 | return __hwspin_lock_timeout(hwlock, to, HWLOCK_IRQ, NULL); | 243 | return __hwspin_lock_timeout(hwlock, to, HWLOCK_IRQ, NULL); |
243 | } | 244 | } |
244 | 245 | ||
246 | static inline | ||
247 | int hwspin_lock_timeout_can_sleep(struct hwspinlock *hwlock, unsigned int to) | ||
248 | { | ||
249 | return __hwspin_lock_timeout(hwlock, to, HWLOCK_MUTEX, NULL); | ||
250 | } | ||
251 | |||
245 | /** | 252 | /** |
246 | * hwspin_lock_timeout() - lock an hwspinlock with timeout limit | 253 | * hwspin_lock_timeout() - lock an hwspinlock with timeout limit |
247 | * @hwlock: the hwspinlock to be locked | 254 | * @hwlock: the hwspinlock to be locked |
@@ -301,6 +308,11 @@ static inline void hwspin_unlock_irq(struct hwspinlock *hwlock) | |||
301 | __hwspin_unlock(hwlock, HWLOCK_IRQ, NULL); | 308 | __hwspin_unlock(hwlock, HWLOCK_IRQ, NULL); |
302 | } | 309 | } |
303 | 310 | ||
311 | static inline void hwspin_unlock_can_sleep(struct hwspinlock *hwlock) | ||
312 | { | ||
313 | __hwspin_unlock(hwlock, HWLOCK_MUTEX, NULL); | ||
314 | } | ||
315 | |||
304 | /** | 316 | /** |
305 | * hwspin_unlock() - unlock hwspinlock | 317 | * hwspin_unlock() - unlock hwspinlock |
306 | * @hwlock: a previously-acquired hwspinlock which we want to unlock | 318 | * @hwlock: a previously-acquired hwspinlock which we want to unlock |
diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 50220cab738c..05b63a1e9f84 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h | |||
@@ -53,6 +53,13 @@ | |||
53 | 53 | ||
54 | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr)) | 54 | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr)) |
55 | 55 | ||
56 | #define u64_to_user_ptr(x) ( \ | ||
57 | { \ | ||
58 | typecheck(u64, x); \ | ||
59 | (void __user *)(uintptr_t)x; \ | ||
60 | } \ | ||
61 | ) | ||
62 | |||
56 | /* | 63 | /* |
57 | * This looks more complex than it should be. But we need to | 64 | * This looks more complex than it should be. But we need to |
58 | * get the type for the ~ right in round_down (it needs to be | 65 | * get the type for the ~ right in round_down (it needs to be |
diff --git a/include/linux/memblock.h b/include/linux/memblock.h index f88a536f8069..e3d461f19cbc 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h | |||
@@ -84,6 +84,7 @@ int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size); | |||
84 | int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size); | 84 | int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size); |
85 | int memblock_mark_mirror(phys_addr_t base, phys_addr_t size); | 85 | int memblock_mark_mirror(phys_addr_t base, phys_addr_t size); |
86 | int memblock_mark_nomap(phys_addr_t base, phys_addr_t size); | 86 | int memblock_mark_nomap(phys_addr_t base, phys_addr_t size); |
87 | int memblock_clear_nomap(phys_addr_t base, phys_addr_t size); | ||
87 | ulong choose_memblock_flags(void); | 88 | ulong choose_memblock_flags(void); |
88 | 89 | ||
89 | /* Low level functions */ | 90 | /* Low level functions */ |
@@ -325,10 +326,12 @@ phys_addr_t memblock_mem_size(unsigned long limit_pfn); | |||
325 | phys_addr_t memblock_start_of_DRAM(void); | 326 | phys_addr_t memblock_start_of_DRAM(void); |
326 | phys_addr_t memblock_end_of_DRAM(void); | 327 | phys_addr_t memblock_end_of_DRAM(void); |
327 | void memblock_enforce_memory_limit(phys_addr_t memory_limit); | 328 | void memblock_enforce_memory_limit(phys_addr_t memory_limit); |
328 | int memblock_is_memory(phys_addr_t addr); | 329 | void memblock_cap_memory_range(phys_addr_t base, phys_addr_t size); |
330 | void memblock_mem_limit_remove_map(phys_addr_t limit); | ||
331 | bool memblock_is_memory(phys_addr_t addr); | ||
329 | int memblock_is_map_memory(phys_addr_t addr); | 332 | int memblock_is_map_memory(phys_addr_t addr); |
330 | int memblock_is_region_memory(phys_addr_t base, phys_addr_t size); | 333 | int memblock_is_region_memory(phys_addr_t base, phys_addr_t size); |
331 | int memblock_is_reserved(phys_addr_t addr); | 334 | bool memblock_is_reserved(phys_addr_t addr); |
332 | bool memblock_is_region_reserved(phys_addr_t base, phys_addr_t size); | 335 | bool memblock_is_region_reserved(phys_addr_t base, phys_addr_t size); |
333 | 336 | ||
334 | extern void __memblock_dump_all(void); | 337 | extern void __memblock_dump_all(void); |
diff --git a/include/linux/mm.h b/include/linux/mm.h index e51aafbc4b3a..f29e8aa76e39 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -2157,14 +2157,18 @@ kernel_map_pages(struct page *page, int numpages, int enable) | |||
2157 | } | 2157 | } |
2158 | #ifdef CONFIG_HIBERNATION | 2158 | #ifdef CONFIG_HIBERNATION |
2159 | extern bool kernel_page_present(struct page *page); | 2159 | extern bool kernel_page_present(struct page *page); |
2160 | #endif /* CONFIG_HIBERNATION */ | 2160 | #endif /* CONFIG_HIBERNATION */ |
2161 | #else | 2161 | #else /* CONFIG_DEBUG_PAGEALLOC */ |
2162 | static inline void | 2162 | static inline void |
2163 | kernel_map_pages(struct page *page, int numpages, int enable) {} | 2163 | kernel_map_pages(struct page *page, int numpages, int enable) {} |
2164 | #ifdef CONFIG_HIBERNATION | 2164 | #ifdef CONFIG_HIBERNATION |
2165 | static inline bool kernel_page_present(struct page *page) { return true; } | 2165 | static inline bool kernel_page_present(struct page *page) { return true; } |
2166 | #endif /* CONFIG_HIBERNATION */ | 2166 | #endif /* CONFIG_HIBERNATION */ |
2167 | #endif | 2167 | static inline bool debug_pagealloc_enabled(void) |
2168 | { | ||
2169 | return false; | ||
2170 | } | ||
2171 | #endif /* CONFIG_DEBUG_PAGEALLOC */ | ||
2168 | 2172 | ||
2169 | #ifdef __HAVE_ARCH_GATE_AREA | 2173 | #ifdef __HAVE_ARCH_GATE_AREA |
2170 | extern struct vm_area_struct *get_gate_vma(struct mm_struct *mm); | 2174 | extern struct vm_area_struct *get_gate_vma(struct mm_struct *mm); |
diff --git a/include/linux/platform_data/davinci_asp.h b/include/linux/platform_data/davinci_asp.h index 85ad68f9206a..4ed28436d187 100644 --- a/include/linux/platform_data/davinci_asp.h +++ b/include/linux/platform_data/davinci_asp.h | |||
@@ -86,6 +86,8 @@ struct davinci_mcasp_pdata { | |||
86 | u8 rxnumevt; | 86 | u8 rxnumevt; |
87 | int tx_dma_channel; | 87 | int tx_dma_channel; |
88 | int rx_dma_channel; | 88 | int rx_dma_channel; |
89 | |||
90 | bool shared_dai; | ||
89 | }; | 91 | }; |
90 | /* TODO: Fix arch/arm/mach-davinci/ users and remove this define */ | 92 | /* TODO: Fix arch/arm/mach-davinci/ users and remove this define */ |
91 | #define snd_platform_data davinci_mcasp_pdata | 93 | #define snd_platform_data davinci_mcasp_pdata |
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h index 4c82c2d5d5f8..d68441b560fa 100644 --- a/include/linux/remoteproc.h +++ b/include/linux/remoteproc.h | |||
@@ -450,6 +450,7 @@ enum rproc_crash_type { | |||
450 | * @fw_version: human readable version information extracted from f/w | 450 | * @fw_version: human readable version information extracted from f/w |
451 | * @has_iommu: flag to indicate if remote processor is behind an MMU | 451 | * @has_iommu: flag to indicate if remote processor is behind an MMU |
452 | * @use_userspace_loader: flag to denote if remoteproc is loaded by userspace | 452 | * @use_userspace_loader: flag to denote if remoteproc is loaded by userspace |
453 | * @late_attach: flag indicating remote core has been externally pre-loaded | ||
453 | */ | 454 | */ |
454 | struct rproc { | 455 | struct rproc { |
455 | struct list_head node; | 456 | struct list_head node; |
@@ -486,6 +487,7 @@ struct rproc { | |||
486 | char *fw_version; | 487 | char *fw_version; |
487 | bool has_iommu; | 488 | bool has_iommu; |
488 | bool use_userspace_loader; | 489 | bool use_userspace_loader; |
490 | u32 late_attach; | ||
489 | }; | 491 | }; |
490 | 492 | ||
491 | /* we currently support only two vrings per rvdev */ | 493 | /* we currently support only two vrings per rvdev */ |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 4b73fe206f37..43daf00967a6 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -1171,7 +1171,7 @@ bool cpus_share_cache(int this_cpu, int that_cpu); | |||
1171 | typedef const struct cpumask *(*sched_domain_mask_f)(int cpu); | 1171 | typedef const struct cpumask *(*sched_domain_mask_f)(int cpu); |
1172 | typedef int (*sched_domain_flags_f)(void); | 1172 | typedef int (*sched_domain_flags_f)(void); |
1173 | typedef | 1173 | typedef |
1174 | const struct sched_group_energy * const(*sched_domain_energy_f)(int cpu); | 1174 | const struct sched_group_energy *(*sched_domain_energy_f)(int cpu); |
1175 | 1175 | ||
1176 | #define SDTL_OVERLAP 0x01 | 1176 | #define SDTL_OVERLAP 0x01 |
1177 | 1177 | ||
diff --git a/include/uapi/drm/omap_drm.h b/include/uapi/drm/omap_drm.h index 72e461e1e5bc..7e7322498992 100644 --- a/include/uapi/drm/omap_drm.h +++ b/include/uapi/drm/omap_drm.h | |||
@@ -36,6 +36,9 @@ struct drm_omap_param { | |||
36 | #define OMAP_BO_SCANOUT 0x00000001 /* scanout capable (phys contiguous) */ | 36 | #define OMAP_BO_SCANOUT 0x00000001 /* scanout capable (phys contiguous) */ |
37 | #define OMAP_BO_CACHE_MASK 0x00000006 /* cache type mask, see cache modes */ | 37 | #define OMAP_BO_CACHE_MASK 0x00000006 /* cache type mask, see cache modes */ |
38 | #define OMAP_BO_TILED_MASK 0x00000f00 /* tiled mapping mask, see tiled modes */ | 38 | #define OMAP_BO_TILED_MASK 0x00000f00 /* tiled mapping mask, see tiled modes */ |
39 | #define OMAP_BO_MEM_CONTIG 0x00000008 /* only use contiguous dma mem */ | ||
40 | #define OMAP_BO_MEM_TILER 0x00000010 /* only use TILER mem */ | ||
41 | #define OMAP_BO_MEM_PIN 0x00000020 /* pin the buffer when allocating */ | ||
39 | 42 | ||
40 | /* cache modes */ | 43 | /* cache modes */ |
41 | #define OMAP_BO_CACHED 0x00000000 /* default */ | 44 | #define OMAP_BO_CACHED 0x00000000 /* default */ |
diff --git a/include/uapi/linux/hwspinlock_user.h b/include/uapi/linux/hwspinlock_user.h new file mode 100644 index 000000000000..68f3dff70c7f --- /dev/null +++ b/include/uapi/linux/hwspinlock_user.h | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | * Userspace interface to hardware spinlocks | ||
3 | * | ||
4 | * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com | ||
5 | * | ||
6 | * Redistribution and use in source and binary forms, with or without | ||
7 | * modification, are permitted provided that the following conditions | ||
8 | * are met: | ||
9 | * | ||
10 | * * Redistributions of source code must retain the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer. | ||
12 | * * Redistributions in binary form must reproduce the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer in | ||
14 | * the documentation and/or other materials provided with the | ||
15 | * distribution. | ||
16 | * * Neither the name Texas Instruments nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived | ||
18 | * from this software without specific prior written permission. | ||
19 | * | ||
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
23 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
24 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
25 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
26 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
27 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
28 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
31 | */ | ||
32 | |||
33 | #ifndef _UAPI_HWSPINLOCK_USER_H | ||
34 | #define _UAPI_HWSPINLOCK_USER_H | ||
35 | |||
36 | #include <linux/ioctl.h> | ||
37 | |||
38 | /** | ||
39 | * struct hwspinlock_user_lock - Sent to lock a specific hwspinlock | ||
40 | * @id: hardware spinlock id | ||
41 | * @timeout: timeout value in msecs | ||
42 | */ | ||
43 | struct hwspinlock_user_lock { | ||
44 | int id; | ||
45 | unsigned int timeout; | ||
46 | }; | ||
47 | |||
48 | /** | ||
49 | * struct hwspinlock_user_unlock - Sent to unlock a specific hwspinlock | ||
50 | * @id: hardware spinlock id | ||
51 | */ | ||
52 | struct hwspinlock_user_unlock { | ||
53 | int id; | ||
54 | }; | ||
55 | |||
56 | #define HWSPINLOCK_IOC_MAGIC 'h' | ||
57 | |||
58 | #define HWSPINLOCK_USER_LOCK _IOW(HWSPINLOCK_IOC_MAGIC, 0, \ | ||
59 | struct hwspinlock_user_lock) | ||
60 | #define HWSPINLOCK_USER_UNLOCK _IOW(HWSPINLOCK_IOC_MAGIC, 1, \ | ||
61 | struct hwspinlock_user_unlock) | ||
62 | |||
63 | #endif /* _UAPI_HWSPINLOCK_USER_H */ | ||
diff --git a/include/uapi/linux/kexec.h b/include/uapi/linux/kexec.h index 99048e501b88..aae5ebf2022b 100644 --- a/include/uapi/linux/kexec.h +++ b/include/uapi/linux/kexec.h | |||
@@ -39,6 +39,7 @@ | |||
39 | #define KEXEC_ARCH_SH (42 << 16) | 39 | #define KEXEC_ARCH_SH (42 << 16) |
40 | #define KEXEC_ARCH_MIPS_LE (10 << 16) | 40 | #define KEXEC_ARCH_MIPS_LE (10 << 16) |
41 | #define KEXEC_ARCH_MIPS ( 8 << 16) | 41 | #define KEXEC_ARCH_MIPS ( 8 << 16) |
42 | #define KEXEC_ARCH_AARCH64 (183 << 16) | ||
42 | 43 | ||
43 | /* The artificial cap on the number of segments passed to kexec_load. */ | 44 | /* The artificial cap on the number of segments passed to kexec_load. */ |
44 | #define KEXEC_SEGMENT_MAX 16 | 45 | #define KEXEC_SEGMENT_MAX 16 |
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index 5f5b66a2f156..f3a097fbf72a 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig | |||
@@ -228,6 +228,7 @@ config ENABLE_DEFAULT_TRACERS | |||
228 | bool "Trace process context switches and events" | 228 | bool "Trace process context switches and events" |
229 | depends on !GENERIC_TRACER | 229 | depends on !GENERIC_TRACER |
230 | select TRACING | 230 | select TRACING |
231 | select GPU_TRACEPOINTS | ||
231 | help | 232 | help |
232 | This tracer hooks to various trace points in the kernel, | 233 | This tracer hooks to various trace points in the kernel, |
233 | allowing the user to pick and choose which trace point they | 234 | allowing the user to pick and choose which trace point they |
diff --git a/mm/memblock.c b/mm/memblock.c index da06771223d8..007b6fc1da9b 100644 --- a/mm/memblock.c +++ b/mm/memblock.c | |||
@@ -835,6 +835,18 @@ int __init_memblock memblock_mark_nomap(phys_addr_t base, phys_addr_t size) | |||
835 | } | 835 | } |
836 | 836 | ||
837 | /** | 837 | /** |
838 | * memblock_clear_nomap - Clear flag MEMBLOCK_NOMAP for a specified region. | ||
839 | * @base: the base phys addr of the region | ||
840 | * @size: the size of the region | ||
841 | * | ||
842 | * Return 0 on success, -errno on failure. | ||
843 | */ | ||
844 | int __init_memblock memblock_clear_nomap(phys_addr_t base, phys_addr_t size) | ||
845 | { | ||
846 | return memblock_setclr_flag(base, size, 0, MEMBLOCK_NOMAP); | ||
847 | } | ||
848 | |||
849 | /** | ||
838 | * __next_reserved_mem_region - next function for for_each_reserved_region() | 850 | * __next_reserved_mem_region - next function for for_each_reserved_region() |
839 | * @idx: pointer to u64 loop variable | 851 | * @idx: pointer to u64 loop variable |
840 | * @out_start: ptr to phys_addr_t for start address of the region, can be %NULL | 852 | * @out_start: ptr to phys_addr_t for start address of the region, can be %NULL |
@@ -1486,15 +1498,16 @@ phys_addr_t __init_memblock memblock_end_of_DRAM(void) | |||
1486 | return (memblock.memory.regions[idx].base + memblock.memory.regions[idx].size); | 1498 | return (memblock.memory.regions[idx].base + memblock.memory.regions[idx].size); |
1487 | } | 1499 | } |
1488 | 1500 | ||
1489 | void __init memblock_enforce_memory_limit(phys_addr_t limit) | 1501 | static phys_addr_t __init_memblock __find_max_addr(phys_addr_t limit) |
1490 | { | 1502 | { |
1491 | phys_addr_t max_addr = (phys_addr_t)ULLONG_MAX; | 1503 | phys_addr_t max_addr = (phys_addr_t)ULLONG_MAX; |
1492 | struct memblock_region *r; | 1504 | struct memblock_region *r; |
1493 | 1505 | ||
1494 | if (!limit) | 1506 | /* |
1495 | return; | 1507 | * translate the memory @limit size into the max address within one of |
1496 | 1508 | * the memory memblock regions, if the @limit exceeds the total size | |
1497 | /* find out max address */ | 1509 | * of those regions, max_addr will keep original value ULLONG_MAX |
1510 | */ | ||
1498 | for_each_memblock(memory, r) { | 1511 | for_each_memblock(memory, r) { |
1499 | if (limit <= r->size) { | 1512 | if (limit <= r->size) { |
1500 | max_addr = r->base + limit; | 1513 | max_addr = r->base + limit; |
@@ -1503,6 +1516,22 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit) | |||
1503 | limit -= r->size; | 1516 | limit -= r->size; |
1504 | } | 1517 | } |
1505 | 1518 | ||
1519 | return max_addr; | ||
1520 | } | ||
1521 | |||
1522 | void __init memblock_enforce_memory_limit(phys_addr_t limit) | ||
1523 | { | ||
1524 | phys_addr_t max_addr = (phys_addr_t)ULLONG_MAX; | ||
1525 | |||
1526 | if (!limit) | ||
1527 | return; | ||
1528 | |||
1529 | max_addr = __find_max_addr(limit); | ||
1530 | |||
1531 | /* @limit exceeds the total size of the memory, do nothing */ | ||
1532 | if (max_addr == (phys_addr_t)ULLONG_MAX) | ||
1533 | return; | ||
1534 | |||
1506 | /* truncate both memory and reserved regions */ | 1535 | /* truncate both memory and reserved regions */ |
1507 | memblock_remove_range(&memblock.memory, max_addr, | 1536 | memblock_remove_range(&memblock.memory, max_addr, |
1508 | (phys_addr_t)ULLONG_MAX); | 1537 | (phys_addr_t)ULLONG_MAX); |
@@ -1510,6 +1539,50 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit) | |||
1510 | (phys_addr_t)ULLONG_MAX); | 1539 | (phys_addr_t)ULLONG_MAX); |
1511 | } | 1540 | } |
1512 | 1541 | ||
1542 | void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size) | ||
1543 | { | ||
1544 | int start_rgn, end_rgn; | ||
1545 | int i, ret; | ||
1546 | |||
1547 | if (!size) | ||
1548 | return; | ||
1549 | |||
1550 | ret = memblock_isolate_range(&memblock.memory, base, size, | ||
1551 | &start_rgn, &end_rgn); | ||
1552 | if (ret) | ||
1553 | return; | ||
1554 | |||
1555 | /* remove all the MAP regions */ | ||
1556 | for (i = memblock.memory.cnt - 1; i >= end_rgn; i--) | ||
1557 | if (!memblock_is_nomap(&memblock.memory.regions[i])) | ||
1558 | memblock_remove_region(&memblock.memory, i); | ||
1559 | |||
1560 | for (i = start_rgn - 1; i >= 0; i--) | ||
1561 | if (!memblock_is_nomap(&memblock.memory.regions[i])) | ||
1562 | memblock_remove_region(&memblock.memory, i); | ||
1563 | |||
1564 | /* truncate the reserved regions */ | ||
1565 | memblock_remove_range(&memblock.reserved, 0, base); | ||
1566 | memblock_remove_range(&memblock.reserved, | ||
1567 | base + size, (phys_addr_t)ULLONG_MAX); | ||
1568 | } | ||
1569 | |||
1570 | void __init memblock_mem_limit_remove_map(phys_addr_t limit) | ||
1571 | { | ||
1572 | phys_addr_t max_addr; | ||
1573 | |||
1574 | if (!limit) | ||
1575 | return; | ||
1576 | |||
1577 | max_addr = __find_max_addr(limit); | ||
1578 | |||
1579 | /* @limit exceeds the total size of the memory, do nothing */ | ||
1580 | if (max_addr == (phys_addr_t)ULLONG_MAX) | ||
1581 | return; | ||
1582 | |||
1583 | memblock_cap_memory_range(0, max_addr); | ||
1584 | } | ||
1585 | |||
1513 | static int __init_memblock memblock_search(struct memblock_type *type, phys_addr_t addr) | 1586 | static int __init_memblock memblock_search(struct memblock_type *type, phys_addr_t addr) |
1514 | { | 1587 | { |
1515 | unsigned int left = 0, right = type->cnt; | 1588 | unsigned int left = 0, right = type->cnt; |
@@ -1528,12 +1601,12 @@ static int __init_memblock memblock_search(struct memblock_type *type, phys_addr | |||
1528 | return -1; | 1601 | return -1; |
1529 | } | 1602 | } |
1530 | 1603 | ||
1531 | int __init memblock_is_reserved(phys_addr_t addr) | 1604 | bool __init memblock_is_reserved(phys_addr_t addr) |
1532 | { | 1605 | { |
1533 | return memblock_search(&memblock.reserved, addr) != -1; | 1606 | return memblock_search(&memblock.reserved, addr) != -1; |
1534 | } | 1607 | } |
1535 | 1608 | ||
1536 | int __init_memblock memblock_is_memory(phys_addr_t addr) | 1609 | bool __init_memblock memblock_is_memory(phys_addr_t addr) |
1537 | { | 1610 | { |
1538 | return memblock_search(&memblock.memory, addr) != -1; | 1611 | return memblock_search(&memblock.memory, addr) != -1; |
1539 | } | 1612 | } |
@@ -1670,6 +1670,14 @@ static void kmem_rcu_free(struct rcu_head *head) | |||
1670 | } | 1670 | } |
1671 | 1671 | ||
1672 | #if DEBUG | 1672 | #if DEBUG |
1673 | static bool is_debug_pagealloc_cache(struct kmem_cache *cachep) | ||
1674 | { | ||
1675 | if (debug_pagealloc_enabled() && OFF_SLAB(cachep) && | ||
1676 | (cachep->size % PAGE_SIZE) == 0) | ||
1677 | return true; | ||
1678 | |||
1679 | return false; | ||
1680 | } | ||
1673 | 1681 | ||
1674 | #ifdef CONFIG_DEBUG_PAGEALLOC | 1682 | #ifdef CONFIG_DEBUG_PAGEALLOC |
1675 | static void store_stackinfo(struct kmem_cache *cachep, unsigned long *addr, | 1683 | static void store_stackinfo(struct kmem_cache *cachep, unsigned long *addr, |
@@ -1703,6 +1711,23 @@ static void store_stackinfo(struct kmem_cache *cachep, unsigned long *addr, | |||
1703 | } | 1711 | } |
1704 | *addr++ = 0x87654321; | 1712 | *addr++ = 0x87654321; |
1705 | } | 1713 | } |
1714 | |||
1715 | static void slab_kernel_map(struct kmem_cache *cachep, void *objp, | ||
1716 | int map, unsigned long caller) | ||
1717 | { | ||
1718 | if (!is_debug_pagealloc_cache(cachep)) | ||
1719 | return; | ||
1720 | |||
1721 | if (caller) | ||
1722 | store_stackinfo(cachep, objp, caller); | ||
1723 | |||
1724 | kernel_map_pages(virt_to_page(objp), cachep->size / PAGE_SIZE, map); | ||
1725 | } | ||
1726 | |||
1727 | #else | ||
1728 | static inline void slab_kernel_map(struct kmem_cache *cachep, void *objp, | ||
1729 | int map, unsigned long caller) {} | ||
1730 | |||
1706 | #endif | 1731 | #endif |
1707 | 1732 | ||
1708 | static void poison_obj(struct kmem_cache *cachep, void *addr, unsigned char val) | 1733 | static void poison_obj(struct kmem_cache *cachep, void *addr, unsigned char val) |
@@ -1781,6 +1806,9 @@ static void check_poison_obj(struct kmem_cache *cachep, void *objp) | |||
1781 | int size, i; | 1806 | int size, i; |
1782 | int lines = 0; | 1807 | int lines = 0; |
1783 | 1808 | ||
1809 | if (is_debug_pagealloc_cache(cachep)) | ||
1810 | return; | ||
1811 | |||
1784 | realobj = (char *)objp + obj_offset(cachep); | 1812 | realobj = (char *)objp + obj_offset(cachep); |
1785 | size = cachep->object_size; | 1813 | size = cachep->object_size; |
1786 | 1814 | ||
@@ -1846,16 +1874,8 @@ static void slab_destroy_debugcheck(struct kmem_cache *cachep, | |||
1846 | void *objp = index_to_obj(cachep, page, i); | 1874 | void *objp = index_to_obj(cachep, page, i); |
1847 | 1875 | ||
1848 | if (cachep->flags & SLAB_POISON) { | 1876 | if (cachep->flags & SLAB_POISON) { |
1849 | #ifdef CONFIG_DEBUG_PAGEALLOC | ||
1850 | if (cachep->size % PAGE_SIZE == 0 && | ||
1851 | OFF_SLAB(cachep)) | ||
1852 | kernel_map_pages(virt_to_page(objp), | ||
1853 | cachep->size / PAGE_SIZE, 1); | ||
1854 | else | ||
1855 | check_poison_obj(cachep, objp); | ||
1856 | #else | ||
1857 | check_poison_obj(cachep, objp); | 1877 | check_poison_obj(cachep, objp); |
1858 | #endif | 1878 | slab_kernel_map(cachep, objp, 1, 0); |
1859 | } | 1879 | } |
1860 | if (cachep->flags & SLAB_RED_ZONE) { | 1880 | if (cachep->flags & SLAB_RED_ZONE) { |
1861 | if (*dbg_redzone1(cachep, objp) != RED_INACTIVE) | 1881 | if (*dbg_redzone1(cachep, objp) != RED_INACTIVE) |
@@ -2179,7 +2199,6 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags) | |||
2179 | else | 2199 | else |
2180 | size += BYTES_PER_WORD; | 2200 | size += BYTES_PER_WORD; |
2181 | } | 2201 | } |
2182 | #if FORCED_DEBUG && defined(CONFIG_DEBUG_PAGEALLOC) | ||
2183 | /* | 2202 | /* |
2184 | * To activate debug pagealloc, off-slab management is necessary | 2203 | * To activate debug pagealloc, off-slab management is necessary |
2185 | * requirement. In early phase of initialization, small sized slab | 2204 | * requirement. In early phase of initialization, small sized slab |
@@ -2187,14 +2206,14 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags) | |||
2187 | * to check size >= 256. It guarantees that all necessary small | 2206 | * to check size >= 256. It guarantees that all necessary small |
2188 | * sized slab is initialized in current slab initialization sequence. | 2207 | * sized slab is initialized in current slab initialization sequence. |
2189 | */ | 2208 | */ |
2190 | if (!slab_early_init && size >= kmalloc_size(INDEX_NODE) && | 2209 | if (debug_pagealloc_enabled() && (flags & SLAB_POISON) && |
2210 | !slab_early_init && size >= kmalloc_size(INDEX_NODE) && | ||
2191 | size >= 256 && cachep->object_size > cache_line_size() && | 2211 | size >= 256 && cachep->object_size > cache_line_size() && |
2192 | ALIGN(size, cachep->align) < PAGE_SIZE) { | 2212 | ALIGN(size, cachep->align) < PAGE_SIZE) { |
2193 | cachep->obj_offset += PAGE_SIZE - ALIGN(size, cachep->align); | 2213 | cachep->obj_offset += PAGE_SIZE - ALIGN(size, cachep->align); |
2194 | size = PAGE_SIZE; | 2214 | size = PAGE_SIZE; |
2195 | } | 2215 | } |
2196 | #endif | 2216 | #endif |
2197 | #endif | ||
2198 | 2217 | ||
2199 | /* | 2218 | /* |
2200 | * Determine if the slab management is 'on' or 'off' slab. | 2219 | * Determine if the slab management is 'on' or 'off' slab. |
@@ -2237,15 +2256,6 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags) | |||
2237 | if (flags & CFLGS_OFF_SLAB) { | 2256 | if (flags & CFLGS_OFF_SLAB) { |
2238 | /* really off slab. No need for manual alignment */ | 2257 | /* really off slab. No need for manual alignment */ |
2239 | freelist_size = calculate_freelist_size(cachep->num, 0); | 2258 | freelist_size = calculate_freelist_size(cachep->num, 0); |
2240 | |||
2241 | #ifdef CONFIG_PAGE_POISONING | ||
2242 | /* If we're going to use the generic kernel_map_pages() | ||
2243 | * poisoning, then it's going to smash the contents of | ||
2244 | * the redzone and userword anyhow, so switch them off. | ||
2245 | */ | ||
2246 | if (size % PAGE_SIZE == 0 && flags & SLAB_POISON) | ||
2247 | flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER); | ||
2248 | #endif | ||
2249 | } | 2259 | } |
2250 | 2260 | ||
2251 | cachep->colour_off = cache_line_size(); | 2261 | cachep->colour_off = cache_line_size(); |
@@ -2261,7 +2271,19 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags) | |||
2261 | cachep->size = size; | 2271 | cachep->size = size; |
2262 | cachep->reciprocal_buffer_size = reciprocal_value(size); | 2272 | cachep->reciprocal_buffer_size = reciprocal_value(size); |
2263 | 2273 | ||
2264 | if (flags & CFLGS_OFF_SLAB) { | 2274 | #if DEBUG |
2275 | /* | ||
2276 | * If we're going to use the generic kernel_map_pages() | ||
2277 | * poisoning, then it's going to smash the contents of | ||
2278 | * the redzone and userword anyhow, so switch them off. | ||
2279 | */ | ||
2280 | if (IS_ENABLED(CONFIG_PAGE_POISONING) && | ||
2281 | (cachep->flags & SLAB_POISON) && | ||
2282 | is_debug_pagealloc_cache(cachep)) | ||
2283 | cachep->flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER); | ||
2284 | #endif | ||
2285 | |||
2286 | if (OFF_SLAB(cachep)) { | ||
2265 | cachep->freelist_cache = kmalloc_slab(freelist_size, 0u); | 2287 | cachep->freelist_cache = kmalloc_slab(freelist_size, 0u); |
2266 | /* | 2288 | /* |
2267 | * This is a possibility for one of the kmalloc_{dma,}_caches. | 2289 | * This is a possibility for one of the kmalloc_{dma,}_caches. |
@@ -2488,9 +2510,6 @@ static void cache_init_objs(struct kmem_cache *cachep, | |||
2488 | for (i = 0; i < cachep->num; i++) { | 2510 | for (i = 0; i < cachep->num; i++) { |
2489 | void *objp = index_to_obj(cachep, page, i); | 2511 | void *objp = index_to_obj(cachep, page, i); |
2490 | #if DEBUG | 2512 | #if DEBUG |
2491 | /* need to poison the objs? */ | ||
2492 | if (cachep->flags & SLAB_POISON) | ||
2493 | poison_obj(cachep, objp, POISON_FREE); | ||
2494 | if (cachep->flags & SLAB_STORE_USER) | 2513 | if (cachep->flags & SLAB_STORE_USER) |
2495 | *dbg_userword(cachep, objp) = NULL; | 2514 | *dbg_userword(cachep, objp) = NULL; |
2496 | 2515 | ||
@@ -2514,10 +2533,11 @@ static void cache_init_objs(struct kmem_cache *cachep, | |||
2514 | slab_error(cachep, "constructor overwrote the" | 2533 | slab_error(cachep, "constructor overwrote the" |
2515 | " start of an object"); | 2534 | " start of an object"); |
2516 | } | 2535 | } |
2517 | if ((cachep->size % PAGE_SIZE) == 0 && | 2536 | /* need to poison the objs? */ |
2518 | OFF_SLAB(cachep) && cachep->flags & SLAB_POISON) | 2537 | if (cachep->flags & SLAB_POISON) { |
2519 | kernel_map_pages(virt_to_page(objp), | 2538 | poison_obj(cachep, objp, POISON_FREE); |
2520 | cachep->size / PAGE_SIZE, 0); | 2539 | slab_kernel_map(cachep, objp, 0, 0); |
2540 | } | ||
2521 | #else | 2541 | #else |
2522 | if (cachep->ctor) | 2542 | if (cachep->ctor) |
2523 | cachep->ctor(objp); | 2543 | cachep->ctor(objp); |
@@ -2736,17 +2756,8 @@ static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp, | |||
2736 | 2756 | ||
2737 | set_obj_status(page, objnr, OBJECT_FREE); | 2757 | set_obj_status(page, objnr, OBJECT_FREE); |
2738 | if (cachep->flags & SLAB_POISON) { | 2758 | if (cachep->flags & SLAB_POISON) { |
2739 | #ifdef CONFIG_DEBUG_PAGEALLOC | ||
2740 | if ((cachep->size % PAGE_SIZE)==0 && OFF_SLAB(cachep)) { | ||
2741 | store_stackinfo(cachep, objp, caller); | ||
2742 | kernel_map_pages(virt_to_page(objp), | ||
2743 | cachep->size / PAGE_SIZE, 0); | ||
2744 | } else { | ||
2745 | poison_obj(cachep, objp, POISON_FREE); | ||
2746 | } | ||
2747 | #else | ||
2748 | poison_obj(cachep, objp, POISON_FREE); | 2759 | poison_obj(cachep, objp, POISON_FREE); |
2749 | #endif | 2760 | slab_kernel_map(cachep, objp, 0, caller); |
2750 | } | 2761 | } |
2751 | return objp; | 2762 | return objp; |
2752 | } | 2763 | } |
@@ -2873,15 +2884,8 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep, | |||
2873 | if (!objp) | 2884 | if (!objp) |
2874 | return objp; | 2885 | return objp; |
2875 | if (cachep->flags & SLAB_POISON) { | 2886 | if (cachep->flags & SLAB_POISON) { |
2876 | #ifdef CONFIG_DEBUG_PAGEALLOC | ||
2877 | if ((cachep->size % PAGE_SIZE) == 0 && OFF_SLAB(cachep)) | ||
2878 | kernel_map_pages(virt_to_page(objp), | ||
2879 | cachep->size / PAGE_SIZE, 1); | ||
2880 | else | ||
2881 | check_poison_obj(cachep, objp); | ||
2882 | #else | ||
2883 | check_poison_obj(cachep, objp); | 2887 | check_poison_obj(cachep, objp); |
2884 | #endif | 2888 | slab_kernel_map(cachep, objp, 1, 0); |
2885 | poison_obj(cachep, objp, POISON_INUSE); | 2889 | poison_obj(cachep, objp, POISON_INUSE); |
2886 | } | 2890 | } |
2887 | if (cachep->flags & SLAB_STORE_USER) | 2891 | if (cachep->flags & SLAB_STORE_USER) |
diff --git a/net/rpmsg/rpmsg_proto.c b/net/rpmsg/rpmsg_proto.c index c84cfc4e03c7..010a9aed6dbf 100644 --- a/net/rpmsg/rpmsg_proto.c +++ b/net/rpmsg/rpmsg_proto.c | |||
@@ -543,6 +543,11 @@ static void __rpmsg_proto_cb(struct device *dev, int from_vproc_id, void *data, | |||
543 | len, true); | 543 | len, true); |
544 | #endif | 544 | #endif |
545 | 545 | ||
546 | if (!sk) { | ||
547 | dev_warn(dev, "callback for deleted socket (from %d)\n", src); | ||
548 | return; | ||
549 | } | ||
550 | |||
546 | lock_sock(sk); | 551 | lock_sock(sk); |
547 | 552 | ||
548 | switch (sk->sk_state) { | 553 | switch (sk->sk_state) { |
@@ -618,8 +623,11 @@ static int rpmsg_proto_probe(struct rpmsg_channel *rpdev) | |||
618 | dev_err(dev, "id %d already associated to different vrp\n", | 623 | dev_err(dev, "id %d already associated to different vrp\n", |
619 | id); | 624 | id); |
620 | 625 | ||
621 | if (dst == RPMSG_ADDR_ANY) | 626 | if (dst == RPMSG_ADDR_ANY) { |
627 | /* Set announce to false and avoid extra delay when binding. */ | ||
628 | rpdev->announce = false; | ||
622 | return 0; | 629 | return 0; |
630 | } | ||
623 | 631 | ||
624 | /* associate id/vrp for later lookup in rpmsg_sock_bind() */ | 632 | /* associate id/vrp for later lookup in rpmsg_sock_bind() */ |
625 | if (!vrp) { | 633 | if (!vrp) { |
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index c159042b1eb6..426dd52f6a05 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c | |||
@@ -1713,6 +1713,11 @@ static struct davinci_mcasp_pdata *davinci_mcasp_set_pdata_from_of( | |||
1713 | if (ret >= 0) | 1713 | if (ret >= 0) |
1714 | pdata->sram_size_capture = val; | 1714 | pdata->sram_size_capture = val; |
1715 | 1715 | ||
1716 | if (of_find_property(np, "shared-dai", NULL)) | ||
1717 | pdata->shared_dai = 1; | ||
1718 | else | ||
1719 | pdata->shared_dai = 0; | ||
1720 | |||
1716 | return pdata; | 1721 | return pdata; |
1717 | 1722 | ||
1718 | nodata: | 1723 | nodata: |
@@ -1957,6 +1962,15 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
1957 | 1962 | ||
1958 | pm_runtime_enable(&pdev->dev); | 1963 | pm_runtime_enable(&pdev->dev); |
1959 | 1964 | ||
1965 | /* | ||
1966 | * Forbid runtime PM if the DAI is shared, data transfers will occur | ||
1967 | * from a different core (typically DSP). | ||
1968 | */ | ||
1969 | if (pdata->shared_dai) { | ||
1970 | dev_info(&pdev->dev, "DAI is shared\n"); | ||
1971 | pm_runtime_forbid(&pdev->dev); | ||
1972 | } | ||
1973 | |||
1960 | mcasp->op_mode = pdata->op_mode; | 1974 | mcasp->op_mode = pdata->op_mode; |
1961 | /* sanity check for tdm slots parameter */ | 1975 | /* sanity check for tdm slots parameter */ |
1962 | if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) { | 1976 | if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) { |
@@ -1986,51 +2000,58 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
1986 | 2000 | ||
1987 | mcasp->dev = &pdev->dev; | 2001 | mcasp->dev = &pdev->dev; |
1988 | 2002 | ||
1989 | irq = platform_get_irq_byname(pdev, "common"); | 2003 | /* |
1990 | if (irq >= 0) { | 2004 | * Do not register IRQ if DAI is shared, as the remote core will |
1991 | irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_common", | 2005 | * be responsible for servicing these interrupts. |
1992 | dev_name(&pdev->dev)); | 2006 | */ |
1993 | ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, | 2007 | if (!pdata->shared_dai) { |
1994 | davinci_mcasp_common_irq_handler, | 2008 | irq = platform_get_irq_byname(pdev, "common"); |
1995 | IRQF_ONESHOT | IRQF_SHARED, | 2009 | if (irq >= 0) { |
1996 | irq_name, mcasp); | 2010 | irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, |
1997 | if (ret) { | 2011 | "%s_common", dev_name(&pdev->dev)); |
1998 | dev_err(&pdev->dev, "common IRQ request failed\n"); | 2012 | ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, |
1999 | goto err; | 2013 | davinci_mcasp_common_irq_handler, |
2000 | } | 2014 | IRQF_ONESHOT | IRQF_SHARED, |
2015 | irq_name, mcasp); | ||
2016 | if (ret) { | ||
2017 | dev_err(&pdev->dev, | ||
2018 | "common IRQ request failed\n"); | ||
2019 | goto err; | ||
2020 | } | ||
2001 | 2021 | ||
2002 | mcasp->irq_request[SNDRV_PCM_STREAM_PLAYBACK] = XUNDRN; | 2022 | mcasp->irq_request[SNDRV_PCM_STREAM_PLAYBACK] = XUNDRN; |
2003 | mcasp->irq_request[SNDRV_PCM_STREAM_CAPTURE] = ROVRN; | 2023 | mcasp->irq_request[SNDRV_PCM_STREAM_CAPTURE] = ROVRN; |
2004 | } | 2024 | } |
2005 | 2025 | ||
2006 | irq = platform_get_irq_byname(pdev, "rx"); | 2026 | irq = platform_get_irq_byname(pdev, "rx"); |
2007 | if (irq >= 0) { | 2027 | if (irq >= 0) { |
2008 | irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_rx", | 2028 | irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, |
2009 | dev_name(&pdev->dev)); | 2029 | "%s_rx", dev_name(&pdev->dev)); |
2010 | ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, | 2030 | ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, |
2011 | davinci_mcasp_rx_irq_handler, | 2031 | davinci_mcasp_rx_irq_handler, |
2012 | IRQF_ONESHOT, irq_name, mcasp); | 2032 | IRQF_ONESHOT, irq_name, mcasp); |
2013 | if (ret) { | 2033 | if (ret) { |
2014 | dev_err(&pdev->dev, "RX IRQ request failed\n"); | 2034 | dev_err(&pdev->dev, "RX IRQ request failed\n"); |
2015 | goto err; | 2035 | goto err; |
2016 | } | 2036 | } |
2017 | 2037 | ||
2018 | mcasp->irq_request[SNDRV_PCM_STREAM_CAPTURE] = ROVRN; | 2038 | mcasp->irq_request[SNDRV_PCM_STREAM_CAPTURE] = ROVRN; |
2019 | } | 2039 | } |
2020 | 2040 | ||
2021 | irq = platform_get_irq_byname(pdev, "tx"); | 2041 | irq = platform_get_irq_byname(pdev, "tx"); |
2022 | if (irq >= 0) { | 2042 | if (irq >= 0) { |
2023 | irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_tx", | 2043 | irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, |
2024 | dev_name(&pdev->dev)); | 2044 | "%s_tx", dev_name(&pdev->dev)); |
2025 | ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, | 2045 | ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, |
2026 | davinci_mcasp_tx_irq_handler, | 2046 | davinci_mcasp_tx_irq_handler, |
2027 | IRQF_ONESHOT, irq_name, mcasp); | 2047 | IRQF_ONESHOT, irq_name, mcasp); |
2028 | if (ret) { | 2048 | if (ret) { |
2029 | dev_err(&pdev->dev, "TX IRQ request failed\n"); | 2049 | dev_err(&pdev->dev, "TX IRQ request failed\n"); |
2030 | goto err; | 2050 | goto err; |
2031 | } | 2051 | } |
2032 | 2052 | ||
2033 | mcasp->irq_request[SNDRV_PCM_STREAM_PLAYBACK] = XUNDRN; | 2053 | mcasp->irq_request[SNDRV_PCM_STREAM_PLAYBACK] = XUNDRN; |
2054 | } | ||
2034 | } | 2055 | } |
2035 | 2056 | ||
2036 | dat = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat"); | 2057 | dat = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat"); |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 6d442f114136..0124eedcaaa3 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -1082,6 +1082,15 @@ static void soc_set_name_prefix(struct snd_soc_card *card, | |||
1082 | struct snd_soc_component *component) | 1082 | struct snd_soc_component *component) |
1083 | { | 1083 | { |
1084 | int i; | 1084 | int i; |
1085 | int ret; | ||
1086 | |||
1087 | if (component->dev->of_node) { | ||
1088 | ret = of_property_read_string(component->dev->of_node, | ||
1089 | "name-prefix", | ||
1090 | &component->name_prefix); | ||
1091 | if (ret == 0) | ||
1092 | return; | ||
1093 | } | ||
1085 | 1094 | ||
1086 | if (card->codec_conf == NULL) | 1095 | if (card->codec_conf == NULL) |
1087 | return; | 1096 | return; |
diff --git a/ti_config_fragments/android_am57x.cfg b/ti_config_fragments/android_am57x.cfg new file mode 100644 index 000000000000..10afa4079dce --- /dev/null +++ b/ti_config_fragments/android_am57x.cfg | |||
@@ -0,0 +1,12 @@ | |||
1 | ############################################################################### | ||
2 | # TI Android AM57x Config Options | ||
3 | # Use to set additional android options exclusively for TI AM57x products | ||
4 | # Note: | ||
5 | # Use android/configs/android-base.cfg to set google android base options | ||
6 | # Use android/configs/android-recommended.cfg to set google android | ||
7 | # recommended options | ||
8 | # Use ti_config_fragments/android_omap.cfg to set common android options between | ||
9 | # dra7 and am57 products | ||
10 | ############################################################################### | ||
11 | |||
12 | CONFIG_CMDLINE="root=/dev/mmcblk0p2 rw init=/init rootfstype=ext4 rootwait drm.rnodes=1 androidboot.selinux=permissive snd.slots_reserved=1,1 snd-soc-core.pmdown_time=-1 uio_pdrv_genirq.of_id=generic-uio" | ||
diff --git a/ti_config_fragments/android_omap.cfg b/ti_config_fragments/android_omap.cfg index f82289719a1f..55ccf7851202 100644 --- a/ti_config_fragments/android_omap.cfg +++ b/ti_config_fragments/android_omap.cfg | |||
@@ -8,5 +8,68 @@ | |||
8 | ############################################################################### | 8 | ############################################################################### |
9 | CONFIG_MODULES=y | 9 | CONFIG_MODULES=y |
10 | # CONFIG_USB_G_NOKIA is not set | 10 | # CONFIG_USB_G_NOKIA is not set |
11 | CONFIG_CMDLINE="root=/dev/mmcblk1p2 rw console=ttyO0,119200 androidboot.console=ttyO0 init=/init rootfstype=ext4 rootwait drm.rnodes=1" | 11 | CONFIG_CMDLINE="root=/dev/mmcblk0p2 rw init=/init rootfstype=ext4 rootwait drm.rnodes=1 androidboot.selinux=permissive snd.slots_reserved=1,1 snd-soc-core.pmdown_time=-1 uio_pdrv_genirq.of_id=generic-uio console=ttyS0,115200 androidboot.console=ttyS0 androidboot.hardware=jacinto6evmboard" |
12 | CONFIG_CMDLINE_EXTEND=y | 12 | CONFIG_CMDLINE_EXTEND=y |
13 | |||
14 | # Enable SquashFS | ||
15 | # CONFIG_KERNEL_LZMA is not set | ||
16 | CONFIG_KERNEL_LZO=y | ||
17 | CONFIG_SQUASHFS_XATTR=y | ||
18 | CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y | ||
19 | CONFIG_SQUASHFS_FILE_DIRECT=y | ||
20 | CONFIG_SQUASHFS_LZ4=y | ||
21 | |||
22 | # USB DWC3 | ||
23 | CONFIG_USB_DWC3=y | ||
24 | CONFIG_USB_DWC3_OMAP=y | ||
25 | # USB Mass Storage | ||
26 | CONFIG_SCSI=y | ||
27 | CONFIG_BLK_DEV_SD=y | ||
28 | CONFIG_USB_STORAGE=y | ||
29 | |||
30 | # Extcon drivers | ||
31 | CONFIG_EXTCON=y | ||
32 | CONFIG_EXTCON_PALMAS=y | ||
33 | CONFIG_EXTCON_USB_GPIO=y | ||
34 | |||
35 | # Networking | ||
36 | CONFIG_IP_NF_NAT=y | ||
37 | |||
38 | # IPC | ||
39 | CONFIG_OMAP_REMOTEPROC=y | ||
40 | CONFIG_RPMSG_RPC=y | ||
41 | |||
42 | # Firmware loader Helper needed by IPC | ||
43 | CONFIG_FW_LOADER_USER_HELPER=y | ||
44 | CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y | ||
45 | |||
46 | # Misc. | ||
47 | CONFIG_DEVTMPFS=n | ||
48 | CONFIG_DEVMEM=y | ||
49 | |||
50 | # SW_SYNC | ||
51 | CONFIG_SW_SYNC=y | ||
52 | CONFIG_SW_SYNC_USER=y | ||
53 | |||
54 | #CAN | ||
55 | CONFIG_CAN=y | ||
56 | CONFIG_CAN_C_CAN=y | ||
57 | CONFIG_CAN_C_CAN_PLATFORM=y | ||
58 | |||
59 | # Watchdog Device Drivers | ||
60 | CONFIG_OMAP_WATCHDOG=y | ||
61 | |||
62 | # Wi-Fi | ||
63 | CONFIG_MAC80211=y | ||
64 | CONFIG_CFG80211=y | ||
65 | CONFIG_WL_TI=y | ||
66 | CONFIG_WL18XX=y | ||
67 | CONFIG_WLCORE=y | ||
68 | CONFIG_WLCORE_SPI=y | ||
69 | CONFIG_WLCORE_SDIO=y | ||
70 | |||
71 | # Disable /proc/config.gz | ||
72 | CONFIG_IKCONFIG_PROC=n | ||
73 | |||
74 | # Ftrace | ||
75 | CONFIG_FTRACE=y | ||
diff --git a/ti_config_fragments/audio_display.cfg b/ti_config_fragments/audio_display.cfg index 3952164356df..8925c31049fe 100644 --- a/ti_config_fragments/audio_display.cfg +++ b/ti_config_fragments/audio_display.cfg | |||
@@ -54,6 +54,7 @@ CONFIG_DISPLAY_DRA7EVM_ENCODER_TPD12S015=y | |||
54 | CONFIG_DISPLAY_ENCODER_TPD12S015=y | 54 | CONFIG_DISPLAY_ENCODER_TPD12S015=y |
55 | CONFIG_DISPLAY_ENCODER_SII9022=y | 55 | CONFIG_DISPLAY_ENCODER_SII9022=y |
56 | CONFIG_DISPLAY_ENCODER_TC358768=y | 56 | CONFIG_DISPLAY_ENCODER_TC358768=y |
57 | CONFIG_VIDEO_TI_FPD3_SERDES=y | ||
57 | 58 | ||
58 | # sound | 59 | # sound |
59 | 60 | ||
diff --git a/ti_config_fragments/auto.cfg b/ti_config_fragments/auto.cfg new file mode 100644 index 000000000000..6bbcc9bec063 --- /dev/null +++ b/ti_config_fragments/auto.cfg | |||
@@ -0,0 +1,48 @@ | |||
1 | ################################################## | ||
2 | # TI automotive config options | ||
3 | ################################################## | ||
4 | |||
5 | # | ||
6 | # Connectivity options | ||
7 | # | ||
8 | CONFIG_TOUCHSCREEN_EDT_FT5X06=y | ||
9 | CONFIG_TOUCHSCREEN_GOODIX=y | ||
10 | # | ||
11 | # Audio/Display options | ||
12 | # | ||
13 | CONFIG_SND_SIMPLE_CARD=y | ||
14 | CONFIG_SND_SOC_TLV320AIC3X=y | ||
15 | CONFIG_SND_SOC_HDMI_CODEC=y | ||
16 | CONFIG_SND_OMAP_SOC_HDMI_AUDIO=y | ||
17 | |||
18 | #Hardware spinlock | ||
19 | CONFIG_HWSPINLOCK_USER=y | ||
20 | |||
21 | #User-space I/O | ||
22 | CONFIG_UIO=y | ||
23 | CONFIG_UIO_PDRV_GENIRQ=y | ||
24 | |||
25 | #Video subsystem options | ||
26 | CONFIG_VIDEO_TI_CAL=y | ||
27 | CONFIG_VIDEO_TI_VIP=y | ||
28 | CONFIG_VIDEO_TI_VPE=y | ||
29 | CONFIG_VIDEO_TI_VPDMA_HELPER=y | ||
30 | CONFIG_VIDEO_TI_VPDMA_LOAD_FW=y | ||
31 | CONFIG_VIDEO_OV1063X=y | ||
32 | CONFIG_GPIO_PCA953X=y | ||
33 | CONFIG_VIDEO_OV490=y | ||
34 | |||
35 | #JAMR and Vision options | ||
36 | CONFIG_VIDEO_TVP5158=y | ||
37 | CONFIG_GPIO_MCP23S08=y | ||
38 | |||
39 | #Debug related | ||
40 | CONFIG_DEBUG_LL=y | ||
41 | CONFIG_DEBUG_OMAP2UART1=y | ||
42 | CONFIG_EARLY_PRINTK=y | ||
43 | CONFIG_DEBUG_GPIO=n | ||
44 | |||
45 | #Turn off un-necessary drivers | ||
46 | CONFIG_SENSORS_LM90=n | ||
47 | CONFIG_SENSORS_LM95245=n | ||
48 | CONFIG_ICS932S401=n | ||
diff --git a/ti_config_fragments/connectivity.cfg b/ti_config_fragments/connectivity.cfg index e4853308e3d3..d1d7ed1eccc4 100644 --- a/ti_config_fragments/connectivity.cfg +++ b/ti_config_fragments/connectivity.cfg | |||
@@ -296,10 +296,11 @@ CONFIG_EXTCON_USB_GPIO=m | |||
296 | 296 | ||
297 | #Touchscreen/ADC | 297 | #Touchscreen/ADC |
298 | CONFIG_TOUCHSCREEN_EDT_FT5X06=m | 298 | CONFIG_TOUCHSCREEN_EDT_FT5X06=m |
299 | CONFIG_TOUCHSCREEN_PIXCIR=m | 299 | CONFIG_TOUCHSCREEN_PIXCIR=y |
300 | CONFIG_TOUCHSCREEN_TI_AM335X_TSC=m | 300 | CONFIG_TOUCHSCREEN_TI_AM335X_TSC=m |
301 | CONFIG_TOUCHSCREEN_GOODIX=m | 301 | CONFIG_TOUCHSCREEN_GOODIX=m |
302 | CONFIG_TI_AM335X_ADC=m | 302 | CONFIG_TI_AM335X_ADC=m |
303 | CONFIG_TOUCHSCREEN_LDC3001=y | ||
303 | 304 | ||
304 | #QSPI | 305 | #QSPI |
305 | CONFIG_SPI_CADENCE_QUADSPI=m | 306 | CONFIG_SPI_CADENCE_QUADSPI=m |
diff --git a/ti_config_fragments/defconfig_map.txt b/ti_config_fragments/defconfig_map.txt index 5a0ed65087ec..4f637b8b5a3a 100644 --- a/ti_config_fragments/defconfig_map.txt +++ b/ti_config_fragments/defconfig_map.txt | |||
@@ -1,7 +1,7 @@ | |||
1 | # Release Defconfigs | 1 | # Release Defconfigs |
2 | classification: SDK_Release_Defconfigs type: ti_sdk_am3x_release defconfig: multi_v7_defconfig config_file: None extra_configs: multi_v7_prune.cfg baseport.cfg ipc.cfg connectivity.cfg audio_display.cfg wlan.cfg omap_soc.cfg am33xx_only.cfg systemd.cfg | 2 | classification: SDK_Release_Defconfigs type: ti_sdk_am3x_release defconfig: multi_v7_defconfig config_file: None extra_configs: multi_v7_prune.cfg baseport.cfg ipc.cfg connectivity.cfg audio_display.cfg wlan.cfg omap_soc.cfg am33xx_only.cfg systemd.cfg |
3 | classification: SDK_Release_Defconfigs type: ti_sdk_am4x_release defconfig: multi_v7_defconfig config_file: None extra_configs: multi_v7_prune.cfg baseport.cfg ipc.cfg connectivity.cfg audio_display.cfg wlan.cfg omap_soc.cfg am43xx_only.cfg systemd.cfg | 3 | classification: SDK_Release_Defconfigs type: ti_sdk_am4x_release defconfig: multi_v7_defconfig config_file: None extra_configs: multi_v7_prune.cfg baseport.cfg ipc.cfg connectivity.cfg audio_display.cfg wlan.cfg omap_soc.cfg am43xx_only.cfg systemd.cfg |
4 | classification: SDK_Release_Defconfigs type: ti_sdk_dra7x_release defconfig: multi_v7_defconfig config_file: None extra_configs: multi_v7_prune.cfg baseport.cfg ipc.cfg connectivity.cfg audio_display.cfg wlan.cfg omap_soc.cfg lpae.cfg dra7_only.cfg systemd.cfg | 4 | classification: SDK_Release_Defconfigs type: ti_sdk_dra7x_release defconfig: multi_v7_defconfig config_file: None extra_configs: multi_v7_prune.cfg baseport.cfg ipc.cfg connectivity.cfg audio_display.cfg wlan.cfg omap_soc.cfg lpae.cfg dra7_only.cfg systemd.cfg auto.cfg |
5 | classification: SDK_Release_Defconfigs type: ti_sdk_omap2_release defconfig: multi_v7_defconfig config_file: None extra_configs: multi_v7_prune.cfg baseport.cfg ipc.cfg connectivity.cfg audio_display.cfg wlan.cfg omap_soc.cfg systemd.cfg | 5 | classification: SDK_Release_Defconfigs type: ti_sdk_omap2_release defconfig: multi_v7_defconfig config_file: None extra_configs: multi_v7_prune.cfg baseport.cfg ipc.cfg connectivity.cfg audio_display.cfg wlan.cfg omap_soc.cfg systemd.cfg |
6 | classification: SDK_Release_Defconfigs type: ti_sdk_k2g_release defconfig: multi_v7_defconfig config_file: None extra_configs: multi_v7_prune.cfg baseport.cfg ipc.cfg connectivity.cfg audio_display.cfg keystone.cfg lpae.cfg k2g_only.cfg systemd.cfg | 6 | classification: SDK_Release_Defconfigs type: ti_sdk_k2g_release defconfig: multi_v7_defconfig config_file: None extra_configs: multi_v7_prune.cfg baseport.cfg ipc.cfg connectivity.cfg audio_display.cfg keystone.cfg lpae.cfg k2g_only.cfg systemd.cfg |
7 | classification: SDK_Release_Defconfigs type: ti_sdk_keystone_release defconfig: multi_v7_defconfig config_file: None extra_configs: multi_v7_prune.cfg baseport.cfg ipc.cfg connectivity.cfg audio_display.cfg keystone.cfg lpae.cfg systemd.cfg | 7 | classification: SDK_Release_Defconfigs type: ti_sdk_keystone_release defconfig: multi_v7_defconfig config_file: None extra_configs: multi_v7_prune.cfg baseport.cfg ipc.cfg connectivity.cfg audio_display.cfg keystone.cfg lpae.cfg systemd.cfg |
@@ -27,5 +27,7 @@ classification: SDK_Debug_Defconfigs type: ti_sdk_omap2_rt_debug defconfig: mult | |||
27 | classification: SDK_Debug_Defconfigs type: ti_sdk_k2g_rt_debug defconfig: multi_v7_defconfig config_file: None extra_configs: multi_v7_prune.cfg baseport.cfg ipc.cfg connectivity.cfg audio_display.cfg keystone.cfg lpae.cfg k2g_only.cfg real_time.cfg systemd.cfg debug_options.cfg | 27 | classification: SDK_Debug_Defconfigs type: ti_sdk_k2g_rt_debug defconfig: multi_v7_defconfig config_file: None extra_configs: multi_v7_prune.cfg baseport.cfg ipc.cfg connectivity.cfg audio_display.cfg keystone.cfg lpae.cfg k2g_only.cfg real_time.cfg systemd.cfg debug_options.cfg |
28 | classification: SDK_Debug_Defconfigs type: ti_sdk_keystone_rt_debug defconfig: multi_v7_defconfig config_file: None extra_configs: multi_v7_prune.cfg baseport.cfg ipc.cfg connectivity.cfg audio_display.cfg keystone.cfg lpae.cfg real_time.cfg systemd.cfg debug_options.cfg | 28 | classification: SDK_Debug_Defconfigs type: ti_sdk_keystone_rt_debug defconfig: multi_v7_defconfig config_file: None extra_configs: multi_v7_prune.cfg baseport.cfg ipc.cfg connectivity.cfg audio_display.cfg keystone.cfg lpae.cfg real_time.cfg systemd.cfg debug_options.cfg |
29 | # Android Defconfigs | 29 | # Android Defconfigs |
30 | classification: SDK_Release_Defconfigs type: ti_sdk_dra7x_android_release defconfig: multi_v7_defconfig config_file: None extra_configs: multi_v7_prune.cfg baseport.cfg ipc.cfg connectivity.cfg audio_display.cfg wlan.cfg omap_soc.cfg lpae.cfg dra7_only.cfg systemd.cfg ../android/configs/android-base.cfg ../android/configs/android-recommended.cfg | 30 | classification: SDK_Release_Defconfigs type: ti_sdk_dra7x_android_release defconfig: multi_v7_defconfig config_file: None extra_configs: multi_v7_prune.cfg baseport.cfg ipc.cfg connectivity.cfg audio_display.cfg wlan.cfg omap_soc.cfg lpae.cfg dra7_only.cfg systemd.cfg ../android/configs/android-base.cfg ../android/configs/android-recommended.cfg auto.cfg android_omap.cfg |
31 | classification: SDK_Debug_Defconfigs type: ti_sdk_dra7x_android_debug defconfig: multi_v7_defconfig config_file: None extra_configs: multi_v7_prune.cfg baseport.cfg ipc.cfg connectivity.cfg audio_display.cfg wlan.cfg omap_soc.cfg lpae.cfg dra7_only.cfg systemd.cfg debug_options.cfg ../android/configs/android-base.cfg ../android/configs/android-recommended.cfg | 31 | classification: SDK_Release_Defconfigs type: ti_sdk_am57x_android_release defconfig: multi_v7_defconfig config_file: None extra_configs: multi_v7_prune.cfg baseport.cfg ipc.cfg connectivity.cfg audio_display.cfg wlan.cfg omap_soc.cfg lpae.cfg dra7_only.cfg systemd.cfg ../android/configs/android-base.cfg ../android/configs/android-recommended.cfg auto.cfg android_omap.cfg android_am57x.cfg |
32 | classification: SDK_Debug_Defconfigs type: ti_sdk_dra7x_android_debug defconfig: multi_v7_defconfig config_file: None extra_configs: multi_v7_prune.cfg baseport.cfg ipc.cfg connectivity.cfg audio_display.cfg wlan.cfg omap_soc.cfg lpae.cfg dra7_only.cfg systemd.cfg debug_options.cfg ../android/configs/android-base.cfg ../android/configs/android-recommended.cfg auto.cfg android_omap.cfg | ||
33 | classification: SDK_Debug_Defconfigs type: ti_sdk_am57x_android_debug defconfig: multi_v7_defconfig config_file: None extra_configs: multi_v7_prune.cfg baseport.cfg ipc.cfg connectivity.cfg audio_display.cfg wlan.cfg omap_soc.cfg lpae.cfg dra7_only.cfg systemd.cfg debug_options.cfg ../android/configs/android-base.cfg ../android/configs/android-recommended.cfg auto.cfg android_omap.cfg android_am57x.cfg | ||