summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-11-10 18:00:03 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-11-10 18:00:03 -0500
commitb44a3d2a85c64208a57362a1728efb58a6556cd6 (patch)
tree293302b3ac918eb75b442fa035eb976850163b1d
parent56e0464980febfa50432a070261579415c72664e (diff)
parentd13a5c8c4c3dbe299659bcff805f79a2c83e2bbc (diff)
Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC driver updates from Olof Johansson: "As we've enabled multiplatform kernels on ARM, and greatly done away with the contents under arch/arm/mach-*, there's still need for SoC-related drivers to go somewhere. Many of them go in through other driver trees, but we still have drivers/soc to hold some of the "doesn't fit anywhere" lowlevel code that might be shared between ARM and ARM64 (or just in general makes sense to not have under the architecture directory). This branch contains mostly such code: - Drivers for qualcomm SoCs for SMEM, SMD and SMD-RPM, used to communicate with power management blocks on these SoCs for use by clock, regulator and bus frequency drivers. - Allwinner Reduced Serial Bus driver, again used to communicate with PMICs. - Drivers for ARM's SCPI (System Control Processor). Not to be confused with PSCI (Power State Coordination Interface). SCPI is used to communicate with the assistant embedded cores doing power management, and we have yet to see how many of them will implement this for their hardware vs abstracting in other ways (or not at all like in the past). - To make confusion between SCPI and PSCI more likely, this release also includes an update of PSCI to interface version 1.0. - Rockchip support for power domains. - A driver to talk to the firmware on Raspberry Pi" * tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (57 commits) soc: qcom: smd-rpm: Correct size of outgoing message bus: sunxi-rsb: Add driver for Allwinner Reduced Serial Bus bus: sunxi-rsb: Add Allwinner Reduced Serial Bus (RSB) controller bindings ARM: bcm2835: add mutual inclusion protection drivers: psci: make PSCI 1.0 functions initialization version dependent dt-bindings: Correct paths in Rockchip power domains binding document soc: rockchip: power-domain: don't try to print the clock name in error case soc: qcom/smem: add HWSPINLOCK dependency clk: berlin: add cpuclk ARM: berlin: dts: add CLKID_CPU for BG2Q ARM: bcm2835: Add the Raspberry Pi firmware driver soc: qcom: smem: Move RPM message ram out of smem DT node soc: qcom: smd-rpm: Correct the active vs sleep state flagging soc: qcom: smd: delete unneeded of_node_put firmware: qcom-scm: build for correct architecture level soc: qcom: smd: Correct SMEM items for upper channels qcom-scm: add missing prototype for qcom_scm_is_available() qcom-scm: fix endianess issue in __qcom_scm_is_call_available soc: qcom: smd: Reject send of too big packets soc: qcom: smd: Handle big endian CPUs ...
-rw-r--r--Documentation/devicetree/bindings/arm/arm,scpi.txt188
-rw-r--r--Documentation/devicetree/bindings/arm/psci.txt6
-rw-r--r--Documentation/devicetree/bindings/bus/sunxi-rsb.txt47
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/arm,pl172.txt8
-rw-r--r--Documentation/devicetree/bindings/soc/rockchip/power_domain.txt46
-rw-r--r--Documentation/hwmon/scpi-hwmon33
-rw-r--r--MAINTAINERS10
-rw-r--r--arch/arm/boot/dts/qcom-msm8974.dtsi17
-rw-r--r--arch/arm64/kernel/psci.c14
-rw-r--r--drivers/base/power/clock_ops.c6
-rw-r--r--drivers/bus/Kconfig11
-rw-r--r--drivers/bus/Makefile1
-rw-r--r--drivers/bus/sunxi-rsb.c783
-rw-r--r--drivers/clk/Kconfig10
-rw-r--r--drivers/clk/Makefile1
-rw-r--r--drivers/clk/berlin/bg2q.c14
-rw-r--r--drivers/clk/clk-scpi.c325
-rw-r--r--drivers/clocksource/tcb_clksrc.c12
-rw-r--r--drivers/clocksource/timer-atmel-st.c31
-rw-r--r--drivers/cpufreq/Kconfig.arm10
-rw-r--r--drivers/cpufreq/Makefile1
-rw-r--r--drivers/cpufreq/scpi-cpufreq.c124
-rw-r--r--drivers/firmware/Kconfig26
-rw-r--r--drivers/firmware/Makefile4
-rw-r--r--drivers/firmware/arm_scpi.c771
-rw-r--r--drivers/firmware/psci.c108
-rw-r--r--drivers/firmware/qcom_scm-32.c6
-rw-r--r--drivers/firmware/raspberrypi.c260
-rw-r--r--drivers/hwmon/Kconfig8
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/scpi-hwmon.c288
-rw-r--r--drivers/memory/pl172.c26
-rw-r--r--drivers/misc/atmel_tclib.c4
-rw-r--r--drivers/pwm/pwm-atmel-tcb.c26
-rw-r--r--drivers/soc/Kconfig1
-rw-r--r--drivers/soc/Makefile1
-rw-r--r--drivers/soc/qcom/Kconfig17
-rw-r--r--drivers/soc/qcom/smd-rpm.c68
-rw-r--r--drivers/soc/qcom/smd.c296
-rw-r--r--drivers/soc/qcom/smem.c368
-rw-r--r--drivers/soc/rockchip/Kconfig18
-rw-r--r--drivers/soc/rockchip/Makefile4
-rw-r--r--drivers/soc/rockchip/pm_domains.c490
-rw-r--r--include/dt-bindings/clock/berlin2q.h1
-rw-r--r--include/dt-bindings/power/rk3288-power.h31
-rw-r--r--include/linux/atmel_tc.h1
-rw-r--r--include/linux/psci.h2
-rw-r--r--include/linux/qcom_scm.h2
-rw-r--r--include/linux/scpi_protocol.h78
-rw-r--r--include/linux/soc/qcom/smd.h11
-rw-r--r--include/linux/soc/qcom/smem.h2
-rw-r--r--include/linux/sunxi-rsb.h105
-rw-r--r--include/soc/bcm2835/raspberrypi-firmware.h120
-rw-r--r--include/uapi/linux/psci.h18
54 files changed, 4467 insertions, 393 deletions
diff --git a/Documentation/devicetree/bindings/arm/arm,scpi.txt b/Documentation/devicetree/bindings/arm/arm,scpi.txt
new file mode 100644
index 000000000000..86302de67c2c
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/arm,scpi.txt
@@ -0,0 +1,188 @@
1System Control and Power Interface (SCPI) Message Protocol
2----------------------------------------------------------
3
4Firmware implementing the SCPI described in ARM document number ARM DUI 0922B
5("ARM Compute Subsystem SCP: Message Interface Protocols")[0] can be used
6by Linux to initiate various system control and power operations.
7
8Required properties:
9
10- compatible : should be "arm,scpi"
11- mboxes: List of phandle and mailbox channel specifiers
12 All the channels reserved by remote SCP firmware for use by
13 SCPI message protocol should be specified in any order
14- shmem : List of phandle pointing to the shared memory(SHM) area between the
15 processors using these mailboxes for IPC, one for each mailbox
16 SHM can be any memory reserved for the purpose of this communication
17 between the processors.
18
19See Documentation/devicetree/bindings/mailbox/mailbox.txt
20for more details about the generic mailbox controller and
21client driver bindings.
22
23Clock bindings for the clocks based on SCPI Message Protocol
24------------------------------------------------------------
25
26This binding uses the common clock binding[1].
27
28Container Node
29==============
30Required properties:
31- compatible : should be "arm,scpi-clocks"
32 All the clocks provided by SCP firmware via SCPI message
33 protocol much be listed as sub-nodes under this node.
34
35Sub-nodes
36=========
37Required properties:
38- compatible : shall include one of the following
39 "arm,scpi-dvfs-clocks" - all the clocks that are variable and index based.
40 These clocks don't provide an entire range of values between the
41 limits but only discrete points within the range. The firmware
42 provides the mapping for each such operating frequency and the
43 index associated with it. The firmware also manages the
44 voltage scaling appropriately with the clock scaling.
45 "arm,scpi-variable-clocks" - all the clocks that are variable and provide full
46 range within the specified range. The firmware provides the
47 range of values within a specified range.
48
49Other required properties for all clocks(all from common clock binding):
50- #clock-cells : Should be 1. Contains the Clock ID value used by SCPI commands.
51- clock-output-names : shall be the corresponding names of the outputs.
52- clock-indices: The identifying number for the clocks(i.e.clock_id) in the
53 node. It can be non linear and hence provide the mapping of identifiers
54 into the clock-output-names array.
55
56SRAM and Shared Memory for SCPI
57-------------------------------
58
59A small area of SRAM is reserved for SCPI communication between application
60processors and SCP.
61
62Required properties:
63- compatible : should be "arm,juno-sram-ns" for Non-secure SRAM on Juno
64
65The rest of the properties should follow the generic mmio-sram description
66found in ../../misc/sysram.txt
67
68Each sub-node represents the reserved area for SCPI.
69
70Required sub-node properties:
71- reg : The base offset and size of the reserved area with the SRAM
72- compatible : should be "arm,juno-scp-shmem" for Non-secure SRAM based
73 shared memory on Juno platforms
74
75Sensor bindings for the sensors based on SCPI Message Protocol
76--------------------------------------------------------------
77SCPI provides an API to access the various sensors on the SoC.
78
79Required properties:
80- compatible : should be "arm,scpi-sensors".
81- #thermal-sensor-cells: should be set to 1. This property follows the
82 thermal device tree bindings[2].
83
84 Valid cell values are raw identifiers (Sensor
85 ID) as used by the firmware. Refer to
86 platform documentation for your
87 implementation for the IDs to use. For Juno
88 R0 and Juno R1 refer to [3].
89
90[0] http://infocenter.arm.com/help/topic/com.arm.doc.dui0922b/index.html
91[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
92[2] Documentation/devicetree/bindings/thermal/thermal.txt
93[3] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0922b/apas03s22.html
94
95Example:
96
97sram: sram@50000000 {
98 compatible = "arm,juno-sram-ns", "mmio-sram";
99 reg = <0x0 0x50000000 0x0 0x10000>;
100
101 #address-cells = <1>;
102 #size-cells = <1>;
103 ranges = <0 0x0 0x50000000 0x10000>;
104
105 cpu_scp_lpri: scp-shmem@0 {
106 compatible = "arm,juno-scp-shmem";
107 reg = <0x0 0x200>;
108 };
109
110 cpu_scp_hpri: scp-shmem@200 {
111 compatible = "arm,juno-scp-shmem";
112 reg = <0x200 0x200>;
113 };
114};
115
116mailbox: mailbox0@40000000 {
117 ....
118 #mbox-cells = <1>;
119};
120
121scpi_protocol: scpi@2e000000 {
122 compatible = "arm,scpi";
123 mboxes = <&mailbox 0 &mailbox 1>;
124 shmem = <&cpu_scp_lpri &cpu_scp_hpri>;
125
126 clocks {
127 compatible = "arm,scpi-clocks";
128
129 scpi_dvfs: scpi_clocks@0 {
130 compatible = "arm,scpi-dvfs-clocks";
131 #clock-cells = <1>;
132 clock-indices = <0>, <1>, <2>;
133 clock-output-names = "atlclk", "aplclk","gpuclk";
134 };
135 scpi_clk: scpi_clocks@3 {
136 compatible = "arm,scpi-variable-clocks";
137 #clock-cells = <1>;
138 clock-indices = <3>, <4>;
139 clock-output-names = "pxlclk0", "pxlclk1";
140 };
141 };
142
143 scpi_sensors0: sensors {
144 compatible = "arm,scpi-sensors";
145 #thermal-sensor-cells = <1>;
146 };
147};
148
149cpu@0 {
150 ...
151 reg = <0 0>;
152 clocks = <&scpi_dvfs 0>;
153};
154
155hdlcd@7ff60000 {
156 ...
157 reg = <0 0x7ff60000 0 0x1000>;
158 clocks = <&scpi_clk 4>;
159};
160
161thermal-zones {
162 soc_thermal {
163 polling-delay-passive = <100>;
164 polling-delay = <1000>;
165
166 /* sensor ID */
167 thermal-sensors = <&scpi_sensors0 3>;
168 ...
169 };
170};
171
172In the above example, the #clock-cells is set to 1 as required.
173scpi_dvfs has 3 output clocks namely: atlclk, aplclk, and gpuclk with 0,
1741 and 2 as clock-indices. scpi_clk has 2 output clocks namely: pxlclk0
175and pxlclk1 with 3 and 4 as clock-indices.
176
177The first consumer in the example is cpu@0 and it has '0' as the clock
178specifier which points to the first entry in the output clocks of
179scpi_dvfs i.e. "atlclk".
180
181Similarly the second example is hdlcd@7ff60000 and it has pxlclk1 as input
182clock. '4' in the clock specifier here points to the second entry
183in the output clocks of scpi_clocks i.e. "pxlclk1"
184
185The thermal-sensors property in the soc_thermal node uses the
186temperature sensor provided by SCP firmware to setup a thermal
187zone. The ID "3" is the sensor identifier for the temperature sensor
188as used by the firmware.
diff --git a/Documentation/devicetree/bindings/arm/psci.txt b/Documentation/devicetree/bindings/arm/psci.txt
index 5aa40ede0e99..a9adab84e2fe 100644
--- a/Documentation/devicetree/bindings/arm/psci.txt
+++ b/Documentation/devicetree/bindings/arm/psci.txt
@@ -31,6 +31,10 @@ Main node required properties:
31 support, but are permitted to be present for compatibility with 31 support, but are permitted to be present for compatibility with
32 existing software when "arm,psci" is later in the compatible list. 32 existing software when "arm,psci" is later in the compatible list.
33 33
34 * "arm,psci-1.0" : for implementations complying to PSCI 1.0. PSCI 1.0 is
35 backward compatible with PSCI 0.2 with minor specification updates,
36 as defined in the PSCI specification[2].
37
34 - method : The method of calling the PSCI firmware. Permitted 38 - method : The method of calling the PSCI firmware. Permitted
35 values are: 39 values are:
36 40
@@ -100,3 +104,5 @@ Case 3: PSCI v0.2 and PSCI v0.1.
100 104
101[1] Kernel documentation - ARM idle states bindings 105[1] Kernel documentation - ARM idle states bindings
102 Documentation/devicetree/bindings/arm/idle-states.txt 106 Documentation/devicetree/bindings/arm/idle-states.txt
107[2] Power State Coordination Interface (PSCI) specification
108 http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf
diff --git a/Documentation/devicetree/bindings/bus/sunxi-rsb.txt b/Documentation/devicetree/bindings/bus/sunxi-rsb.txt
new file mode 100644
index 000000000000..3dd28343b6ce
--- /dev/null
+++ b/Documentation/devicetree/bindings/bus/sunxi-rsb.txt
@@ -0,0 +1,47 @@
1Allwinner Reduced Serial Bus (RSB) controller
2
3The RSB controller found on later Allwinner SoCs is an SMBus like 2 wire
4serial bus with 1 master and up to 15 slaves. It is represented by a node
5for the controller itself, and child nodes representing the slave devices.
6
7Required properties :
8
9 - reg : Offset and length of the register set for the controller.
10 - compatible : Shall be "allwinner,sun8i-a23-rsb".
11 - interrupts : The interrupt line associated to the RSB controller.
12 - clocks : The gate clk associated to the RSB controller.
13 - resets : The reset line associated to the RSB controller.
14 - #address-cells : shall be 1
15 - #size-cells : shall be 0
16
17Optional properties :
18
19 - clock-frequency : Desired RSB bus clock frequency in Hz. Maximum is 20MHz.
20 If not set this defaults to 3MHz.
21
22Child nodes:
23
24An RSB controller node can contain zero or more child nodes representing
25slave devices on the bus. Child 'reg' properties should contain the slave
26device's hardware address. The hardware address is hardwired in the device,
27which can normally be found in the datasheet.
28
29Example:
30
31 rsb@01f03400 {
32 compatible = "allwinner,sun8i-a23-rsb";
33 reg = <0x01f03400 0x400>;
34 interrupts = <0 39 4>;
35 clocks = <&apb0_gates 3>;
36 clock-frequency = <3000000>;
37 resets = <&apb0_rst 3>;
38 #address-cells = <1>;
39 #size-cells = <0>;
40
41 pmic@3e3 {
42 compatible = "...";
43 reg = <0x3e3>;
44
45 /* ... */
46 };
47 };
diff --git a/Documentation/devicetree/bindings/memory-controllers/arm,pl172.txt b/Documentation/devicetree/bindings/memory-controllers/arm,pl172.txt
index e6df32f9986d..22b77ee02f58 100644
--- a/Documentation/devicetree/bindings/memory-controllers/arm,pl172.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/arm,pl172.txt
@@ -1,8 +1,9 @@
1* Device tree bindings for ARM PL172 MultiPort Memory Controller 1* Device tree bindings for ARM PL172/PL175/PL176 MultiPort Memory Controller
2 2
3Required properties: 3Required properties:
4 4
5- compatible: "arm,pl172", "arm,primecell" 5- compatible: Must be "arm,primecell" and exactly one from
6 "arm,pl172", "arm,pl175" or "arm,pl176".
6 7
7- reg: Must contains offset/length value for controller. 8- reg: Must contains offset/length value for controller.
8 9
@@ -56,7 +57,8 @@ Optional child cs node config properties:
56 57
57- mpmc,extended-wait: Enable extended wait. 58- mpmc,extended-wait: Enable extended wait.
58 59
59- mpmc,buffer-enable: Enable write buffer. 60- mpmc,buffer-enable: Enable write buffer, option is not supported by
61 PL175 and PL176 controllers.
60 62
61- mpmc,write-protect: Enable write protect. 63- mpmc,write-protect: Enable write protect.
62 64
diff --git a/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt b/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt
new file mode 100644
index 000000000000..112756e11802
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt
@@ -0,0 +1,46 @@
1* Rockchip Power Domains
2
3Rockchip processors include support for multiple power domains which can be
4powered up/down by software based on different application scenes to save power.
5
6Required properties for power domain controller:
7- compatible: Should be one of the following.
8 "rockchip,rk3288-power-controller" - for RK3288 SoCs.
9- #power-domain-cells: Number of cells in a power-domain specifier.
10 Should be 1 for multiple PM domains.
11- #address-cells: Should be 1.
12- #size-cells: Should be 0.
13
14Required properties for power domain sub nodes:
15- reg: index of the power domain, should use macros in:
16 "include/dt-bindings/power/rk3288-power.h" - for RK3288 type power domain.
17- clocks (optional): phandles to clocks which need to be enabled while power domain
18 switches state.
19
20Example:
21
22 power: power-controller {
23 compatible = "rockchip,rk3288-power-controller";
24 #power-domain-cells = <1>;
25 #address-cells = <1>;
26 #size-cells = <0>;
27
28 pd_gpu {
29 reg = <RK3288_PD_GPU>;
30 clocks = <&cru ACLK_GPU>;
31 };
32 };
33
34Node of a device using power domains must have a power-domains property,
35containing a phandle to the power device node and an index specifying which
36power domain to use.
37The index should use macros in:
38 "include/dt-bindings/power/rk3288-power.h" - for rk3288 type power domain.
39
40Example of the node using power domain:
41
42 node {
43 /* ... */
44 power-domains = <&power RK3288_PD_GPU>;
45 /* ... */
46 };
diff --git a/Documentation/hwmon/scpi-hwmon b/Documentation/hwmon/scpi-hwmon
new file mode 100644
index 000000000000..4cfcdf2d5eab
--- /dev/null
+++ b/Documentation/hwmon/scpi-hwmon
@@ -0,0 +1,33 @@
1Kernel driver scpi-hwmon
2========================
3
4Supported chips:
5 * Chips based on ARM System Control Processor Interface
6 Addresses scanned: -
7 Datasheet: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0922b/index.html
8
9Author: Punit Agrawal <punit.agrawal@arm.com>
10
11Description
12-----------
13
14This driver supports hardware monitoring for SoC's based on the ARM
15System Control Processor (SCP) implementing the System Control
16Processor Interface (SCPI). The following sensor types are supported
17by the SCP -
18
19 * temperature
20 * voltage
21 * current
22 * power
23
24The SCP interface provides an API to query the available sensors and
25their values which are then exported to userspace by this driver.
26
27Usage Notes
28-----------
29
30The driver relies on device tree node to indicate the presence of SCPI
31support in the kernel. See
32Documentation/devicetree/bindings/arm/arm,scpi.txt for details of the
33devicetree node. \ No newline at end of file
diff --git a/MAINTAINERS b/MAINTAINERS
index 952853712c57..3af5570c2497 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9362,6 +9362,16 @@ W: http://www.sunplus.com
9362S: Supported 9362S: Supported
9363F: arch/score/ 9363F: arch/score/
9364 9364
9365SYSTEM CONTROL & POWER INTERFACE (SCPI) Message Protocol drivers
9366M: Sudeep Holla <sudeep.holla@arm.com>
9367L: linux-arm-kernel@lists.infradead.org
9368S: Maintained
9369F: Documentation/devicetree/bindings/arm/arm,scpi.txt
9370F: drivers/clk/clk-scpi.c
9371F: drivers/cpufreq/scpi-cpufreq.c
9372F: drivers/firmware/arm_scpi.c
9373F: include/linux/scpi_protocol.h
9374
9365SCSI CDROM DRIVER 9375SCSI CDROM DRIVER
9366M: Jens Axboe <axboe@kernel.dk> 9376M: Jens Axboe <axboe@kernel.dk>
9367L: linux-scsi@vger.kernel.org 9377L: linux-scsi@vger.kernel.org
diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi
index ab8e57250468..93e315053bdd 100644
--- a/arch/arm/boot/dts/qcom-msm8974.dtsi
+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
@@ -100,6 +100,15 @@
100 clock-frequency = <19200000>; 100 clock-frequency = <19200000>;
101 }; 101 };
102 102
103 smem {
104 compatible = "qcom,smem";
105
106 memory-region = <&smem_region>;
107 qcom,rpm-msg-ram = <&rpm_msg_ram>;
108
109 hwlocks = <&tcsr_mutex 3>;
110 };
111
103 soc: soc { 112 soc: soc {
104 #address-cells = <1>; 113 #address-cells = <1>;
105 #size-cells = <1>; 114 #size-cells = <1>;
@@ -250,13 +259,9 @@
250 #hwlock-cells = <1>; 259 #hwlock-cells = <1>;
251 }; 260 };
252 261
253 smem@fa00000 { 262 rpm_msg_ram: memory@fc428000 {
254 compatible = "qcom,smem"; 263 compatible = "qcom,rpm-msg-ram";
255
256 memory-region = <&smem_region>;
257 reg = <0xfc428000 0x4000>; 264 reg = <0xfc428000 0x4000>;
258
259 hwlocks = <&tcsr_mutex 3>;
260 }; 265 };
261 266
262 blsp1_uart2: serial@f991e000 { 267 blsp1_uart2: serial@f991e000 {
diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c
index aa94a88f6279..f67f35b6edb1 100644
--- a/arch/arm64/kernel/psci.c
+++ b/arch/arm64/kernel/psci.c
@@ -30,20 +30,6 @@
30#include <asm/smp_plat.h> 30#include <asm/smp_plat.h>
31#include <asm/suspend.h> 31#include <asm/suspend.h>
32 32
33static bool psci_power_state_loses_context(u32 state)
34{
35 return state & PSCI_0_2_POWER_STATE_TYPE_MASK;
36}
37
38static bool psci_power_state_is_valid(u32 state)
39{
40 const u32 valid_mask = PSCI_0_2_POWER_STATE_ID_MASK |
41 PSCI_0_2_POWER_STATE_TYPE_MASK |
42 PSCI_0_2_POWER_STATE_AFFL_MASK;
43
44 return !(state & ~valid_mask);
45}
46
47static DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state); 33static DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state);
48 34
49static int __maybe_unused cpu_psci_cpu_init_idle(unsigned int cpu) 35static int __maybe_unused cpu_psci_cpu_init_idle(unsigned int cpu)
diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c
index fd0973b922a7..60ee5591ee8f 100644
--- a/drivers/base/power/clock_ops.c
+++ b/drivers/base/power/clock_ops.c
@@ -93,7 +93,7 @@ static int __pm_clk_add(struct device *dev, const char *con_id,
93 return -ENOMEM; 93 return -ENOMEM;
94 } 94 }
95 } else { 95 } else {
96 if (IS_ERR(clk) || !__clk_get(clk)) { 96 if (IS_ERR(clk)) {
97 kfree(ce); 97 kfree(ce);
98 return -ENOENT; 98 return -ENOENT;
99 } 99 }
@@ -127,7 +127,9 @@ int pm_clk_add(struct device *dev, const char *con_id)
127 * @clk: Clock pointer 127 * @clk: Clock pointer
128 * 128 *
129 * Add the clock to the list of clocks used for the power management of @dev. 129 * Add the clock to the list of clocks used for the power management of @dev.
130 * It will increment refcount on clock pointer, use clk_put() on it when done. 130 * The power-management code will take control of the clock reference, so
131 * callers should not call clk_put() on @clk after this function sucessfully
132 * returned.
131 */ 133 */
132int pm_clk_add_clk(struct device *dev, struct clk *clk) 134int pm_clk_add_clk(struct device *dev, struct clk *clk)
133{ 135{
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 0ebca8ba7bc4..116b363b7987 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -120,6 +120,17 @@ config SIMPLE_PM_BUS
120 Controller (BSC, sometimes called "LBSC within Bus Bridge", or 120 Controller (BSC, sometimes called "LBSC within Bus Bridge", or
121 "External Bus Interface") as found on several Renesas ARM SoCs. 121 "External Bus Interface") as found on several Renesas ARM SoCs.
122 122
123config SUNXI_RSB
124 tristate "Allwinner sunXi Reduced Serial Bus Driver"
125 default MACH_SUN8I || MACH_SUN9I
126 depends on ARCH_SUNXI
127 select REGMAP
128 help
129 Say y here to enable support for Allwinner's Reduced Serial Bus
130 (RSB) support. This controller is responsible for communicating
131 with various RSB based devices, such as AXP223, AXP8XX PMICs,
132 and AC100/AC200 ICs.
133
123config VEXPRESS_CONFIG 134config VEXPRESS_CONFIG
124 bool "Versatile Express configuration bus" 135 bool "Versatile Express configuration bus"
125 default y if ARCH_VEXPRESS 136 default y if ARCH_VEXPRESS
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index 790e7b933fb2..fcb9f9794a1f 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -15,5 +15,6 @@ obj-$(CONFIG_MVEBU_MBUS) += mvebu-mbus.o
15obj-$(CONFIG_OMAP_INTERCONNECT) += omap_l3_smx.o omap_l3_noc.o 15obj-$(CONFIG_OMAP_INTERCONNECT) += omap_l3_smx.o omap_l3_noc.o
16 16
17obj-$(CONFIG_OMAP_OCP2SCP) += omap-ocp2scp.o 17obj-$(CONFIG_OMAP_OCP2SCP) += omap-ocp2scp.o
18obj-$(CONFIG_SUNXI_RSB) += sunxi-rsb.o
18obj-$(CONFIG_SIMPLE_PM_BUS) += simple-pm-bus.o 19obj-$(CONFIG_SIMPLE_PM_BUS) += simple-pm-bus.o
19obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o 20obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o
diff --git a/drivers/bus/sunxi-rsb.c b/drivers/bus/sunxi-rsb.c
new file mode 100644
index 000000000000..846bc29c157d
--- /dev/null
+++ b/drivers/bus/sunxi-rsb.c
@@ -0,0 +1,783 @@
1/*
2 * RSB (Reduced Serial Bus) driver.
3 *
4 * Author: Chen-Yu Tsai <wens@csie.org>
5 *
6 * This file is licensed under the terms of the GNU General Public License
7 * version 2. This program is licensed "as is" without any warranty of any
8 * kind, whether express or implied.
9 *
10 * The RSB controller looks like an SMBus controller which only supports
11 * byte and word data transfers. But, it differs from standard SMBus
12 * protocol on several aspects:
13 * - it uses addresses set at runtime to address slaves. Runtime addresses
14 * are sent to slaves using their 12bit hardware addresses. Up to 15
15 * runtime addresses are available.
16 * - it adds a parity bit every 8bits of data and address for read and
17 * write accesses; this replaces the ack bit
18 * - only one read access is required to read a byte (instead of a write
19 * followed by a read access in standard SMBus protocol)
20 * - there's no Ack bit after each read access
21 *
22 * This means this bus cannot be used to interface with standard SMBus
23 * devices. Devices known to support this interface include the AXP223,
24 * AXP809, and AXP806 PMICs, and the AC100 audio codec, all from X-Powers.
25 *
26 * A description of the operation and wire protocol can be found in the
27 * RSB section of Allwinner's A80 user manual, which can be found at
28 *
29 * https://github.com/allwinner-zh/documents/tree/master/A80
30 *
31 * This document is officially released by Allwinner.
32 *
33 * This driver is based on i2c-sun6i-p2wi.c, the P2WI bus driver.
34 *
35 */
36
37#include <linux/clk.h>
38#include <linux/clk/clk-conf.h>
39#include <linux/device.h>
40#include <linux/interrupt.h>
41#include <linux/io.h>
42#include <linux/iopoll.h>
43#include <linux/module.h>
44#include <linux/of.h>
45#include <linux/of_irq.h>
46#include <linux/of_platform.h>
47#include <linux/platform_device.h>
48#include <linux/regmap.h>
49#include <linux/reset.h>
50#include <linux/slab.h>
51#include <linux/sunxi-rsb.h>
52#include <linux/types.h>
53
54/* RSB registers */
55#define RSB_CTRL 0x0 /* Global control */
56#define RSB_CCR 0x4 /* Clock control */
57#define RSB_INTE 0x8 /* Interrupt controls */
58#define RSB_INTS 0xc /* Interrupt status */
59#define RSB_ADDR 0x10 /* Address to send with read/write command */
60#define RSB_DATA 0x1c /* Data to read/write */
61#define RSB_LCR 0x24 /* Line control */
62#define RSB_DMCR 0x28 /* Device mode (init) control */
63#define RSB_CMD 0x2c /* RSB Command */
64#define RSB_DAR 0x30 /* Device address / runtime address */
65
66/* CTRL fields */
67#define RSB_CTRL_START_TRANS BIT(7)
68#define RSB_CTRL_ABORT_TRANS BIT(6)
69#define RSB_CTRL_GLOBAL_INT_ENB BIT(1)
70#define RSB_CTRL_SOFT_RST BIT(0)
71
72/* CLK CTRL fields */
73#define RSB_CCR_SDA_OUT_DELAY(v) (((v) & 0x7) << 8)
74#define RSB_CCR_MAX_CLK_DIV 0xff
75#define RSB_CCR_CLK_DIV(v) ((v) & RSB_CCR_MAX_CLK_DIV)
76
77/* STATUS fields */
78#define RSB_INTS_TRANS_ERR_ACK BIT(16)
79#define RSB_INTS_TRANS_ERR_DATA_BIT(v) (((v) >> 8) & 0xf)
80#define RSB_INTS_TRANS_ERR_DATA GENMASK(11, 8)
81#define RSB_INTS_LOAD_BSY BIT(2)
82#define RSB_INTS_TRANS_ERR BIT(1)
83#define RSB_INTS_TRANS_OVER BIT(0)
84
85/* LINE CTRL fields*/
86#define RSB_LCR_SCL_STATE BIT(5)
87#define RSB_LCR_SDA_STATE BIT(4)
88#define RSB_LCR_SCL_CTL BIT(3)
89#define RSB_LCR_SCL_CTL_EN BIT(2)
90#define RSB_LCR_SDA_CTL BIT(1)
91#define RSB_LCR_SDA_CTL_EN BIT(0)
92
93/* DEVICE MODE CTRL field values */
94#define RSB_DMCR_DEVICE_START BIT(31)
95#define RSB_DMCR_MODE_DATA (0x7c << 16)
96#define RSB_DMCR_MODE_REG (0x3e << 8)
97#define RSB_DMCR_DEV_ADDR 0x00
98
99/* CMD values */
100#define RSB_CMD_RD8 0x8b
101#define RSB_CMD_RD16 0x9c
102#define RSB_CMD_RD32 0xa6
103#define RSB_CMD_WR8 0x4e
104#define RSB_CMD_WR16 0x59
105#define RSB_CMD_WR32 0x63
106#define RSB_CMD_STRA 0xe8
107
108/* DAR fields */
109#define RSB_DAR_RTA(v) (((v) & 0xff) << 16)
110#define RSB_DAR_DA(v) ((v) & 0xffff)
111
112#define RSB_MAX_FREQ 20000000
113
114#define RSB_CTRL_NAME "sunxi-rsb"
115
116struct sunxi_rsb_addr_map {
117 u16 hwaddr;
118 u8 rtaddr;
119};
120
121struct sunxi_rsb {
122 struct device *dev;
123 void __iomem *regs;
124 struct clk *clk;
125 struct reset_control *rstc;
126 struct completion complete;
127 struct mutex lock;
128 unsigned int status;
129};
130
131/* bus / slave device related functions */
132static struct bus_type sunxi_rsb_bus;
133
134static int sunxi_rsb_device_match(struct device *dev, struct device_driver *drv)
135{
136 return of_driver_match_device(dev, drv);
137}
138
139static int sunxi_rsb_device_probe(struct device *dev)
140{
141 const struct sunxi_rsb_driver *drv = to_sunxi_rsb_driver(dev->driver);
142 struct sunxi_rsb_device *rdev = to_sunxi_rsb_device(dev);
143 int ret;
144
145 if (!drv->probe)
146 return -ENODEV;
147
148 if (!rdev->irq) {
149 int irq = -ENOENT;
150
151 if (dev->of_node)
152 irq = of_irq_get(dev->of_node, 0);
153
154 if (irq == -EPROBE_DEFER)
155 return irq;
156 if (irq < 0)
157 irq = 0;
158
159 rdev->irq = irq;
160 }
161
162 ret = of_clk_set_defaults(dev->of_node, false);
163 if (ret < 0)
164 return ret;
165
166 return drv->probe(rdev);
167}
168
169static int sunxi_rsb_device_remove(struct device *dev)
170{
171 const struct sunxi_rsb_driver *drv = to_sunxi_rsb_driver(dev->driver);
172
173 return drv->remove(to_sunxi_rsb_device(dev));
174}
175
176static struct bus_type sunxi_rsb_bus = {
177 .name = RSB_CTRL_NAME,
178 .match = sunxi_rsb_device_match,
179 .probe = sunxi_rsb_device_probe,
180 .remove = sunxi_rsb_device_remove,
181};
182
183static void sunxi_rsb_dev_release(struct device *dev)
184{
185 struct sunxi_rsb_device *rdev = to_sunxi_rsb_device(dev);
186
187 kfree(rdev);
188}
189
190/**
191 * sunxi_rsb_device_create() - allocate and add an RSB device
192 * @rsb: RSB controller
193 * @node: RSB slave device node
194 * @hwaddr: RSB slave hardware address
195 * @rtaddr: RSB slave runtime address
196 */
197static struct sunxi_rsb_device *sunxi_rsb_device_create(struct sunxi_rsb *rsb,
198 struct device_node *node, u16 hwaddr, u8 rtaddr)
199{
200 int err;
201 struct sunxi_rsb_device *rdev;
202
203 rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
204 if (!rdev)
205 return ERR_PTR(-ENOMEM);
206
207 rdev->rsb = rsb;
208 rdev->hwaddr = hwaddr;
209 rdev->rtaddr = rtaddr;
210 rdev->dev.bus = &sunxi_rsb_bus;
211 rdev->dev.parent = rsb->dev;
212 rdev->dev.of_node = node;
213 rdev->dev.release = sunxi_rsb_dev_release;
214
215 dev_set_name(&rdev->dev, "%s-%x", RSB_CTRL_NAME, hwaddr);
216
217 err = device_register(&rdev->dev);
218 if (err < 0) {
219 dev_err(&rdev->dev, "Can't add %s, status %d\n",
220 dev_name(&rdev->dev), err);
221 goto err_device_add;
222 }
223
224 dev_dbg(&rdev->dev, "device %s registered\n", dev_name(&rdev->dev));
225
226err_device_add:
227 put_device(&rdev->dev);
228
229 return ERR_PTR(err);
230}
231
232/**
233 * sunxi_rsb_device_unregister(): unregister an RSB device
234 * @rdev: rsb_device to be removed
235 */
236static void sunxi_rsb_device_unregister(struct sunxi_rsb_device *rdev)
237{
238 device_unregister(&rdev->dev);
239}
240
241static int sunxi_rsb_remove_devices(struct device *dev, void *data)
242{
243 struct sunxi_rsb_device *rdev = to_sunxi_rsb_device(dev);
244
245 if (dev->bus == &sunxi_rsb_bus)
246 sunxi_rsb_device_unregister(rdev);
247
248 return 0;
249}
250
251/**
252 * sunxi_rsb_driver_register() - Register device driver with RSB core
253 * @rdrv: device driver to be associated with slave-device.
254 *
255 * This API will register the client driver with the RSB framework.
256 * It is typically called from the driver's module-init function.
257 */
258int sunxi_rsb_driver_register(struct sunxi_rsb_driver *rdrv)
259{
260 rdrv->driver.bus = &sunxi_rsb_bus;
261 return driver_register(&rdrv->driver);
262}
263EXPORT_SYMBOL_GPL(sunxi_rsb_driver_register);
264
265/* common code that starts a transfer */
266static int _sunxi_rsb_run_xfer(struct sunxi_rsb *rsb)
267{
268 if (readl(rsb->regs + RSB_CTRL) & RSB_CTRL_START_TRANS) {
269 dev_dbg(rsb->dev, "RSB transfer still in progress\n");
270 return -EBUSY;
271 }
272
273 reinit_completion(&rsb->complete);
274
275 writel(RSB_INTS_LOAD_BSY | RSB_INTS_TRANS_ERR | RSB_INTS_TRANS_OVER,
276 rsb->regs + RSB_INTE);
277 writel(RSB_CTRL_START_TRANS | RSB_CTRL_GLOBAL_INT_ENB,
278 rsb->regs + RSB_CTRL);
279
280 if (!wait_for_completion_io_timeout(&rsb->complete,
281 msecs_to_jiffies(100))) {
282 dev_dbg(rsb->dev, "RSB timeout\n");
283
284 /* abort the transfer */
285 writel(RSB_CTRL_ABORT_TRANS, rsb->regs + RSB_CTRL);
286
287 /* clear any interrupt flags */
288 writel(readl(rsb->regs + RSB_INTS), rsb->regs + RSB_INTS);
289
290 return -ETIMEDOUT;
291 }
292
293 if (rsb->status & RSB_INTS_LOAD_BSY) {
294 dev_dbg(rsb->dev, "RSB busy\n");
295 return -EBUSY;
296 }
297
298 if (rsb->status & RSB_INTS_TRANS_ERR) {
299 if (rsb->status & RSB_INTS_TRANS_ERR_ACK) {
300 dev_dbg(rsb->dev, "RSB slave nack\n");
301 return -EINVAL;
302 }
303
304 if (rsb->status & RSB_INTS_TRANS_ERR_DATA) {
305 dev_dbg(rsb->dev, "RSB transfer data error\n");
306 return -EIO;
307 }
308 }
309
310 return 0;
311}
312
313static int sunxi_rsb_read(struct sunxi_rsb *rsb, u8 rtaddr, u8 addr,
314 u32 *buf, size_t len)
315{
316 u32 cmd;
317 int ret;
318
319 if (!buf)
320 return -EINVAL;
321
322 switch (len) {
323 case 1:
324 cmd = RSB_CMD_RD8;
325 break;
326 case 2:
327 cmd = RSB_CMD_RD16;
328 break;
329 case 4:
330 cmd = RSB_CMD_RD32;
331 break;
332 default:
333 dev_err(rsb->dev, "Invalid access width: %d\n", len);
334 return -EINVAL;
335 }
336
337 mutex_lock(&rsb->lock);
338
339 writel(addr, rsb->regs + RSB_ADDR);
340 writel(RSB_DAR_RTA(rtaddr), rsb->regs + RSB_DAR);
341 writel(cmd, rsb->regs + RSB_CMD);
342
343 ret = _sunxi_rsb_run_xfer(rsb);
344 if (ret)
345 goto out;
346
347 *buf = readl(rsb->regs + RSB_DATA);
348
349 mutex_unlock(&rsb->lock);
350
351out:
352 return ret;
353}
354
355static int sunxi_rsb_write(struct sunxi_rsb *rsb, u8 rtaddr, u8 addr,
356 const u32 *buf, size_t len)
357{
358 u32 cmd;
359 int ret;
360
361 if (!buf)
362 return -EINVAL;
363
364 switch (len) {
365 case 1:
366 cmd = RSB_CMD_WR8;
367 break;
368 case 2:
369 cmd = RSB_CMD_WR16;
370 break;
371 case 4:
372 cmd = RSB_CMD_WR32;
373 break;
374 default:
375 dev_err(rsb->dev, "Invalid access width: %d\n", len);
376 return -EINVAL;
377 }
378
379 mutex_lock(&rsb->lock);
380
381 writel(addr, rsb->regs + RSB_ADDR);
382 writel(RSB_DAR_RTA(rtaddr), rsb->regs + RSB_DAR);
383 writel(*buf, rsb->regs + RSB_DATA);
384 writel(cmd, rsb->regs + RSB_CMD);
385 ret = _sunxi_rsb_run_xfer(rsb);
386
387 mutex_unlock(&rsb->lock);
388
389 return ret;
390}
391
392/* RSB regmap functions */
393struct sunxi_rsb_ctx {
394 struct sunxi_rsb_device *rdev;
395 int size;
396};
397
398static int regmap_sunxi_rsb_reg_read(void *context, unsigned int reg,
399 unsigned int *val)
400{
401 struct sunxi_rsb_ctx *ctx = context;
402 struct sunxi_rsb_device *rdev = ctx->rdev;
403
404 if (reg > 0xff)
405 return -EINVAL;
406
407 return sunxi_rsb_read(rdev->rsb, rdev->rtaddr, reg, val, ctx->size);
408}
409
410static int regmap_sunxi_rsb_reg_write(void *context, unsigned int reg,
411 unsigned int val)
412{
413 struct sunxi_rsb_ctx *ctx = context;
414 struct sunxi_rsb_device *rdev = ctx->rdev;
415
416 return sunxi_rsb_write(rdev->rsb, rdev->rtaddr, reg, &val, ctx->size);
417}
418
419static void regmap_sunxi_rsb_free_ctx(void *context)
420{
421 struct sunxi_rsb_ctx *ctx = context;
422
423 kfree(ctx);
424}
425
426static struct regmap_bus regmap_sunxi_rsb = {
427 .reg_write = regmap_sunxi_rsb_reg_write,
428 .reg_read = regmap_sunxi_rsb_reg_read,
429 .free_context = regmap_sunxi_rsb_free_ctx,
430 .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
431 .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
432};
433
434static struct sunxi_rsb_ctx *regmap_sunxi_rsb_init_ctx(struct sunxi_rsb_device *rdev,
435 const struct regmap_config *config)
436{
437 struct sunxi_rsb_ctx *ctx;
438
439 switch (config->val_bits) {
440 case 8:
441 case 16:
442 case 32:
443 break;
444 default:
445 return ERR_PTR(-EINVAL);
446 }
447
448 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
449 if (!ctx)
450 return ERR_PTR(-ENOMEM);
451
452 ctx->rdev = rdev;
453 ctx->size = config->val_bits / 8;
454
455 return ctx;
456}
457
458struct regmap *__devm_regmap_init_sunxi_rsb(struct sunxi_rsb_device *rdev,
459 const struct regmap_config *config,
460 struct lock_class_key *lock_key,
461 const char *lock_name)
462{
463 struct sunxi_rsb_ctx *ctx = regmap_sunxi_rsb_init_ctx(rdev, config);
464
465 if (IS_ERR(ctx))
466 return ERR_CAST(ctx);
467
468 return __devm_regmap_init(&rdev->dev, &regmap_sunxi_rsb, ctx, config,
469 lock_key, lock_name);
470}
471EXPORT_SYMBOL_GPL(__devm_regmap_init_sunxi_rsb);
472
473/* RSB controller driver functions */
474static irqreturn_t sunxi_rsb_irq(int irq, void *dev_id)
475{
476 struct sunxi_rsb *rsb = dev_id;
477 u32 status;
478
479 status = readl(rsb->regs + RSB_INTS);
480 rsb->status = status;
481
482 /* Clear interrupts */
483 status &= (RSB_INTS_LOAD_BSY | RSB_INTS_TRANS_ERR |
484 RSB_INTS_TRANS_OVER);
485 writel(status, rsb->regs + RSB_INTS);
486
487 complete(&rsb->complete);
488
489 return IRQ_HANDLED;
490}
491
492static int sunxi_rsb_init_device_mode(struct sunxi_rsb *rsb)
493{
494 int ret = 0;
495 u32 reg;
496
497 /* send init sequence */
498 writel(RSB_DMCR_DEVICE_START | RSB_DMCR_MODE_DATA |
499 RSB_DMCR_MODE_REG | RSB_DMCR_DEV_ADDR, rsb->regs + RSB_DMCR);
500
501 readl_poll_timeout(rsb->regs + RSB_DMCR, reg,
502 !(reg & RSB_DMCR_DEVICE_START), 100, 250000);
503 if (reg & RSB_DMCR_DEVICE_START)
504 ret = -ETIMEDOUT;
505
506 /* clear interrupt status bits */
507 writel(readl(rsb->regs + RSB_INTS), rsb->regs + RSB_INTS);
508
509 return ret;
510}
511
512/*
513 * There are 15 valid runtime addresses, though Allwinner typically
514 * skips the first, for unknown reasons, and uses the following three.
515 *
516 * 0x17, 0x2d, 0x3a, 0x4e, 0x59, 0x63, 0x74, 0x8b,
517 * 0x9c, 0xa6, 0xb1, 0xc5, 0xd2, 0xe8, 0xff
518 *
519 * No designs with 2 RSB slave devices sharing identical hardware
520 * addresses on the same bus have been seen in the wild. All designs
521 * use 0x2d for the primary PMIC, 0x3a for the secondary PMIC if
522 * there is one, and 0x45 for peripheral ICs.
523 *
524 * The hardware does not seem to support re-setting runtime addresses.
525 * Attempts to do so result in the slave devices returning a NACK.
526 * Hence we just hardcode the mapping here, like Allwinner does.
527 */
528
529static const struct sunxi_rsb_addr_map sunxi_rsb_addr_maps[] = {
530 { 0x3e3, 0x2d }, /* Primary PMIC: AXP223, AXP809, AXP81X, ... */
531 { 0x745, 0x3a }, /* Secondary PMIC: AXP806, ... */
532 { 0xe89, 0x45 }, /* Peripheral IC: AC100, ... */
533};
534
535static u8 sunxi_rsb_get_rtaddr(u16 hwaddr)
536{
537 int i;
538
539 for (i = 0; i < ARRAY_SIZE(sunxi_rsb_addr_maps); i++)
540 if (hwaddr == sunxi_rsb_addr_maps[i].hwaddr)
541 return sunxi_rsb_addr_maps[i].rtaddr;
542
543 return 0; /* 0 is an invalid runtime address */
544}
545
546static int of_rsb_register_devices(struct sunxi_rsb *rsb)
547{
548 struct device *dev = rsb->dev;
549 struct device_node *child, *np = dev->of_node;
550 u32 hwaddr;
551 u8 rtaddr;
552 int ret;
553
554 if (!np)
555 return -EINVAL;
556
557 /* Runtime addresses for all slaves should be set first */
558 for_each_available_child_of_node(np, child) {
559 dev_dbg(dev, "setting child %s runtime address\n",
560 child->full_name);
561
562 ret = of_property_read_u32(child, "reg", &hwaddr);
563 if (ret) {
564 dev_err(dev, "%s: invalid 'reg' property: %d\n",
565 child->full_name, ret);
566 continue;
567 }
568
569 rtaddr = sunxi_rsb_get_rtaddr(hwaddr);
570 if (!rtaddr) {
571 dev_err(dev, "%s: unknown hardware device address\n",
572 child->full_name);
573 continue;
574 }
575
576 /*
577 * Since no devices have been registered yet, we are the
578 * only ones using the bus, we can skip locking the bus.
579 */
580
581 /* setup command parameters */
582 writel(RSB_CMD_STRA, rsb->regs + RSB_CMD);
583 writel(RSB_DAR_RTA(rtaddr) | RSB_DAR_DA(hwaddr),
584 rsb->regs + RSB_DAR);
585
586 /* send command */
587 ret = _sunxi_rsb_run_xfer(rsb);
588 if (ret)
589 dev_warn(dev, "%s: set runtime address failed: %d\n",
590 child->full_name, ret);
591 }
592
593 /* Then we start adding devices and probing them */
594 for_each_available_child_of_node(np, child) {
595 struct sunxi_rsb_device *rdev;
596
597 dev_dbg(dev, "adding child %s\n", child->full_name);
598
599 ret = of_property_read_u32(child, "reg", &hwaddr);
600 if (ret)
601 continue;
602
603 rtaddr = sunxi_rsb_get_rtaddr(hwaddr);
604 if (!rtaddr)
605 continue;
606
607 rdev = sunxi_rsb_device_create(rsb, child, hwaddr, rtaddr);
608 if (IS_ERR(rdev))
609 dev_err(dev, "failed to add child device %s: %ld\n",
610 child->full_name, PTR_ERR(rdev));
611 }
612
613 return 0;
614}
615
616static const struct of_device_id sunxi_rsb_of_match_table[] = {
617 { .compatible = "allwinner,sun8i-a23-rsb" },
618 {}
619};
620MODULE_DEVICE_TABLE(of, sunxi_rsb_of_match_table);
621
622static int sunxi_rsb_probe(struct platform_device *pdev)
623{
624 struct device *dev = &pdev->dev;
625 struct device_node *np = dev->of_node;
626 struct resource *r;
627 struct sunxi_rsb *rsb;
628 unsigned long p_clk_freq;
629 u32 clk_delay, clk_freq = 3000000;
630 int clk_div, irq, ret;
631 u32 reg;
632
633 of_property_read_u32(np, "clock-frequency", &clk_freq);
634 if (clk_freq > RSB_MAX_FREQ) {
635 dev_err(dev,
636 "clock-frequency (%u Hz) is too high (max = 20MHz)\n",
637 clk_freq);
638 return -EINVAL;
639 }
640
641 rsb = devm_kzalloc(dev, sizeof(*rsb), GFP_KERNEL);
642 if (!rsb)
643 return -ENOMEM;
644
645 rsb->dev = dev;
646 platform_set_drvdata(pdev, rsb);
647 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
648 rsb->regs = devm_ioremap_resource(dev, r);
649 if (IS_ERR(rsb->regs))
650 return PTR_ERR(rsb->regs);
651
652 irq = platform_get_irq(pdev, 0);
653 if (irq < 0) {
654 dev_err(dev, "failed to retrieve irq: %d\n", irq);
655 return irq;
656 }
657
658 rsb->clk = devm_clk_get(dev, NULL);
659 if (IS_ERR(rsb->clk)) {
660 ret = PTR_ERR(rsb->clk);
661 dev_err(dev, "failed to retrieve clk: %d\n", ret);
662 return ret;
663 }
664
665 ret = clk_prepare_enable(rsb->clk);
666 if (ret) {
667 dev_err(dev, "failed to enable clk: %d\n", ret);
668 return ret;
669 }
670
671 p_clk_freq = clk_get_rate(rsb->clk);
672
673 rsb->rstc = devm_reset_control_get(dev, NULL);
674 if (IS_ERR(rsb->rstc)) {
675 ret = PTR_ERR(rsb->rstc);
676 dev_err(dev, "failed to retrieve reset controller: %d\n", ret);
677 goto err_clk_disable;
678 }
679
680 ret = reset_control_deassert(rsb->rstc);
681 if (ret) {
682 dev_err(dev, "failed to deassert reset line: %d\n", ret);
683 goto err_clk_disable;
684 }
685
686 init_completion(&rsb->complete);
687 mutex_init(&rsb->lock);
688
689 /* reset the controller */
690 writel(RSB_CTRL_SOFT_RST, rsb->regs + RSB_CTRL);
691 readl_poll_timeout(rsb->regs + RSB_CTRL, reg,
692 !(reg & RSB_CTRL_SOFT_RST), 1000, 100000);
693
694 /*
695 * Clock frequency and delay calculation code is from
696 * Allwinner U-boot sources.
697 *
698 * From A83 user manual:
699 * bus clock frequency = parent clock frequency / (2 * (divider + 1))
700 */
701 clk_div = p_clk_freq / clk_freq / 2;
702 if (!clk_div)
703 clk_div = 1;
704 else if (clk_div > RSB_CCR_MAX_CLK_DIV + 1)
705 clk_div = RSB_CCR_MAX_CLK_DIV + 1;
706
707 clk_delay = clk_div >> 1;
708 if (!clk_delay)
709 clk_delay = 1;
710
711 dev_info(dev, "RSB running at %lu Hz\n", p_clk_freq / clk_div / 2);
712 writel(RSB_CCR_SDA_OUT_DELAY(clk_delay) | RSB_CCR_CLK_DIV(clk_div - 1),
713 rsb->regs + RSB_CCR);
714
715 ret = devm_request_irq(dev, irq, sunxi_rsb_irq, 0, RSB_CTRL_NAME, rsb);
716 if (ret) {
717 dev_err(dev, "can't register interrupt handler irq %d: %d\n",
718 irq, ret);
719 goto err_reset_assert;
720 }
721
722 /* initialize all devices on the bus into RSB mode */
723 ret = sunxi_rsb_init_device_mode(rsb);
724 if (ret)
725 dev_warn(dev, "Initialize device mode failed: %d\n", ret);
726
727 of_rsb_register_devices(rsb);
728
729 return 0;
730
731err_reset_assert:
732 reset_control_assert(rsb->rstc);
733
734err_clk_disable:
735 clk_disable_unprepare(rsb->clk);
736
737 return ret;
738}
739
740static int sunxi_rsb_remove(struct platform_device *pdev)
741{
742 struct sunxi_rsb *rsb = platform_get_drvdata(pdev);
743
744 device_for_each_child(rsb->dev, NULL, sunxi_rsb_remove_devices);
745 reset_control_assert(rsb->rstc);
746 clk_disable_unprepare(rsb->clk);
747
748 return 0;
749}
750
751static struct platform_driver sunxi_rsb_driver = {
752 .probe = sunxi_rsb_probe,
753 .remove = sunxi_rsb_remove,
754 .driver = {
755 .name = RSB_CTRL_NAME,
756 .of_match_table = sunxi_rsb_of_match_table,
757 },
758};
759
760static int __init sunxi_rsb_init(void)
761{
762 int ret;
763
764 ret = bus_register(&sunxi_rsb_bus);
765 if (ret) {
766 pr_err("failed to register sunxi sunxi_rsb bus: %d\n", ret);
767 return ret;
768 }
769
770 return platform_driver_register(&sunxi_rsb_driver);
771}
772module_init(sunxi_rsb_init);
773
774static void __exit sunxi_rsb_exit(void)
775{
776 platform_driver_unregister(&sunxi_rsb_driver);
777 bus_unregister(&sunxi_rsb_bus);
778}
779module_exit(sunxi_rsb_exit);
780
781MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
782MODULE_DESCRIPTION("Allwinner sunXi Reduced Serial Bus controller driver");
783MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 7a1ab24052b8..c3e3a02f7f1f 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -60,6 +60,16 @@ config COMMON_CLK_RK808
60 clocked at 32KHz each. Clkout1 is always on, Clkout2 can off 60 clocked at 32KHz each. Clkout1 is always on, Clkout2 can off
61 by control register. 61 by control register.
62 62
63config COMMON_CLK_SCPI
64 tristate "Clock driver controlled via SCPI interface"
65 depends on ARM_SCPI_PROTOCOL || COMPILE_TEST
66 ---help---
67 This driver provides support for clocks that are controlled
68 by firmware that implements the SCPI interface.
69
70 This driver uses SCPI Message Protocol to interact with the
71 firmware providing all the clock controls.
72
63config COMMON_CLK_SI5351 73config COMMON_CLK_SI5351
64 tristate "Clock driver for SiLabs 5351A/B/C" 74 tristate "Clock driver for SiLabs 5351A/B/C"
65 depends on I2C 75 depends on I2C
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index d3e1910eebab..820714c72d36 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_COMMON_CLK_PALMAS) += clk-palmas.o
36obj-$(CONFIG_CLK_QORIQ) += clk-qoriq.o 36obj-$(CONFIG_CLK_QORIQ) += clk-qoriq.o
37obj-$(CONFIG_COMMON_CLK_RK808) += clk-rk808.o 37obj-$(CONFIG_COMMON_CLK_RK808) += clk-rk808.o
38obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o 38obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
39obj-$(CONFIG_COMMON_CLK_SCPI) += clk-scpi.o
39obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o 40obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
40obj-$(CONFIG_COMMON_CLK_SI514) += clk-si514.o 41obj-$(CONFIG_COMMON_CLK_SI514) += clk-si514.o
41obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o 42obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o
diff --git a/drivers/clk/berlin/bg2q.c b/drivers/clk/berlin/bg2q.c
index 243f421abcb4..f144547cf76c 100644
--- a/drivers/clk/berlin/bg2q.c
+++ b/drivers/clk/berlin/bg2q.c
@@ -45,7 +45,7 @@
45#define REG_SDIO0XIN_CLKCTL 0x0158 45#define REG_SDIO0XIN_CLKCTL 0x0158
46#define REG_SDIO1XIN_CLKCTL 0x015c 46#define REG_SDIO1XIN_CLKCTL 0x015c
47 47
48#define MAX_CLKS 27 48#define MAX_CLKS 28
49static struct clk *clks[MAX_CLKS]; 49static struct clk *clks[MAX_CLKS];
50static struct clk_onecell_data clk_data; 50static struct clk_onecell_data clk_data;
51static DEFINE_SPINLOCK(lock); 51static DEFINE_SPINLOCK(lock);
@@ -356,13 +356,13 @@ static void __init berlin2q_clock_setup(struct device_node *np)
356 gd->bit_idx, 0, &lock); 356 gd->bit_idx, 0, &lock);
357 } 357 }
358 358
359 /* 359 /* cpuclk divider is fixed to 1 */
360 * twdclk is derived from cpu/3 360 clks[CLKID_CPU] =
361 * TODO: use cpupll until cpuclk is not available 361 clk_register_fixed_factor(NULL, "cpu", clk_names[CPUPLL],
362 */ 362 0, 1, 1);
363 /* twdclk is derived from cpu/3 */
363 clks[CLKID_TWD] = 364 clks[CLKID_TWD] =
364 clk_register_fixed_factor(NULL, "twd", clk_names[CPUPLL], 365 clk_register_fixed_factor(NULL, "twd", "cpu", 0, 1, 3);
365 0, 1, 3);
366 366
367 /* check for errors on leaf clocks */ 367 /* check for errors on leaf clocks */
368 for (n = 0; n < MAX_CLKS; n++) { 368 for (n = 0; n < MAX_CLKS; n++) {
diff --git a/drivers/clk/clk-scpi.c b/drivers/clk/clk-scpi.c
new file mode 100644
index 000000000000..0b501a9fef92
--- /dev/null
+++ b/drivers/clk/clk-scpi.c
@@ -0,0 +1,325 @@
1/*
2 * System Control and Power Interface (SCPI) Protocol based clock driver
3 *
4 * Copyright (C) 2015 ARM Ltd.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <linux/clk-provider.h>
20#include <linux/device.h>
21#include <linux/err.h>
22#include <linux/of.h>
23#include <linux/module.h>
24#include <linux/of_platform.h>
25#include <linux/platform_device.h>
26#include <linux/scpi_protocol.h>
27
28struct scpi_clk {
29 u32 id;
30 struct clk_hw hw;
31 struct scpi_dvfs_info *info;
32 struct scpi_ops *scpi_ops;
33};
34
35#define to_scpi_clk(clk) container_of(clk, struct scpi_clk, hw)
36
37static struct platform_device *cpufreq_dev;
38
39static unsigned long scpi_clk_recalc_rate(struct clk_hw *hw,
40 unsigned long parent_rate)
41{
42 struct scpi_clk *clk = to_scpi_clk(hw);
43
44 return clk->scpi_ops->clk_get_val(clk->id);
45}
46
47static long scpi_clk_round_rate(struct clk_hw *hw, unsigned long rate,
48 unsigned long *parent_rate)
49{
50 /*
51 * We can't figure out what rate it will be, so just return the
52 * rate back to the caller. scpi_clk_recalc_rate() will be called
53 * after the rate is set and we'll know what rate the clock is
54 * running at then.
55 */
56 return rate;
57}
58
59static int scpi_clk_set_rate(struct clk_hw *hw, unsigned long rate,
60 unsigned long parent_rate)
61{
62 struct scpi_clk *clk = to_scpi_clk(hw);
63
64 return clk->scpi_ops->clk_set_val(clk->id, rate);
65}
66
67static const struct clk_ops scpi_clk_ops = {
68 .recalc_rate = scpi_clk_recalc_rate,
69 .round_rate = scpi_clk_round_rate,
70 .set_rate = scpi_clk_set_rate,
71};
72
73/* find closest match to given frequency in OPP table */
74static int __scpi_dvfs_round_rate(struct scpi_clk *clk, unsigned long rate)
75{
76 int idx;
77 u32 fmin = 0, fmax = ~0, ftmp;
78 const struct scpi_opp *opp = clk->info->opps;
79
80 for (idx = 0; idx < clk->info->count; idx++, opp++) {
81 ftmp = opp->freq;
82 if (ftmp >= (u32)rate) {
83 if (ftmp <= fmax)
84 fmax = ftmp;
85 break;
86 } else if (ftmp >= fmin) {
87 fmin = ftmp;
88 }
89 }
90 return fmax != ~0 ? fmax : fmin;
91}
92
93static unsigned long scpi_dvfs_recalc_rate(struct clk_hw *hw,
94 unsigned long parent_rate)
95{
96 struct scpi_clk *clk = to_scpi_clk(hw);
97 int idx = clk->scpi_ops->dvfs_get_idx(clk->id);
98 const struct scpi_opp *opp;
99
100 if (idx < 0)
101 return 0;
102
103 opp = clk->info->opps + idx;
104 return opp->freq;
105}
106
107static long scpi_dvfs_round_rate(struct clk_hw *hw, unsigned long rate,
108 unsigned long *parent_rate)
109{
110 struct scpi_clk *clk = to_scpi_clk(hw);
111
112 return __scpi_dvfs_round_rate(clk, rate);
113}
114
115static int __scpi_find_dvfs_index(struct scpi_clk *clk, unsigned long rate)
116{
117 int idx, max_opp = clk->info->count;
118 const struct scpi_opp *opp = clk->info->opps;
119
120 for (idx = 0; idx < max_opp; idx++, opp++)
121 if (opp->freq == rate)
122 return idx;
123 return -EINVAL;
124}
125
126static int scpi_dvfs_set_rate(struct clk_hw *hw, unsigned long rate,
127 unsigned long parent_rate)
128{
129 struct scpi_clk *clk = to_scpi_clk(hw);
130 int ret = __scpi_find_dvfs_index(clk, rate);
131
132 if (ret < 0)
133 return ret;
134 return clk->scpi_ops->dvfs_set_idx(clk->id, (u8)ret);
135}
136
137static const struct clk_ops scpi_dvfs_ops = {
138 .recalc_rate = scpi_dvfs_recalc_rate,
139 .round_rate = scpi_dvfs_round_rate,
140 .set_rate = scpi_dvfs_set_rate,
141};
142
143static const struct of_device_id scpi_clk_match[] = {
144 { .compatible = "arm,scpi-dvfs-clocks", .data = &scpi_dvfs_ops, },
145 { .compatible = "arm,scpi-variable-clocks", .data = &scpi_clk_ops, },
146 {}
147};
148
149static struct clk *
150scpi_clk_ops_init(struct device *dev, const struct of_device_id *match,
151 struct scpi_clk *sclk, const char *name)
152{
153 struct clk_init_data init;
154 struct clk *clk;
155 unsigned long min = 0, max = 0;
156
157 init.name = name;
158 init.flags = CLK_IS_ROOT;
159 init.num_parents = 0;
160 init.ops = match->data;
161 sclk->hw.init = &init;
162 sclk->scpi_ops = get_scpi_ops();
163
164 if (init.ops == &scpi_dvfs_ops) {
165 sclk->info = sclk->scpi_ops->dvfs_get_info(sclk->id);
166 if (IS_ERR(sclk->info))
167 return NULL;
168 } else if (init.ops == &scpi_clk_ops) {
169 if (sclk->scpi_ops->clk_get_range(sclk->id, &min, &max) || !max)
170 return NULL;
171 } else {
172 return NULL;
173 }
174
175 clk = devm_clk_register(dev, &sclk->hw);
176 if (!IS_ERR(clk) && max)
177 clk_hw_set_rate_range(&sclk->hw, min, max);
178 return clk;
179}
180
181struct scpi_clk_data {
182 struct scpi_clk **clk;
183 unsigned int clk_num;
184};
185
186static struct clk *
187scpi_of_clk_src_get(struct of_phandle_args *clkspec, void *data)
188{
189 struct scpi_clk *sclk;
190 struct scpi_clk_data *clk_data = data;
191 unsigned int idx = clkspec->args[0], count;
192
193 for (count = 0; count < clk_data->clk_num; count++) {
194 sclk = clk_data->clk[count];
195 if (idx == sclk->id)
196 return sclk->hw.clk;
197 }
198
199 return ERR_PTR(-EINVAL);
200}
201
202static int scpi_clk_add(struct device *dev, struct device_node *np,
203 const struct of_device_id *match)
204{
205 struct clk **clks;
206 int idx, count;
207 struct scpi_clk_data *clk_data;
208
209 count = of_property_count_strings(np, "clock-output-names");
210 if (count < 0) {
211 dev_err(dev, "%s: invalid clock output count\n", np->name);
212 return -EINVAL;
213 }
214
215 clk_data = devm_kmalloc(dev, sizeof(*clk_data), GFP_KERNEL);
216 if (!clk_data)
217 return -ENOMEM;
218
219 clk_data->clk_num = count;
220 clk_data->clk = devm_kcalloc(dev, count, sizeof(*clk_data->clk),
221 GFP_KERNEL);
222 if (!clk_data->clk)
223 return -ENOMEM;
224
225 clks = devm_kcalloc(dev, count, sizeof(*clks), GFP_KERNEL);
226 if (!clks)
227 return -ENOMEM;
228
229 for (idx = 0; idx < count; idx++) {
230 struct scpi_clk *sclk;
231 const char *name;
232 u32 val;
233
234 sclk = devm_kzalloc(dev, sizeof(*sclk), GFP_KERNEL);
235 if (!sclk)
236 return -ENOMEM;
237
238 if (of_property_read_string_index(np, "clock-output-names",
239 idx, &name)) {
240 dev_err(dev, "invalid clock name @ %s\n", np->name);
241 return -EINVAL;
242 }
243
244 if (of_property_read_u32_index(np, "clock-indices",
245 idx, &val)) {
246 dev_err(dev, "invalid clock index @ %s\n", np->name);
247 return -EINVAL;
248 }
249
250 sclk->id = val;
251
252 clks[idx] = scpi_clk_ops_init(dev, match, sclk, name);
253 if (IS_ERR_OR_NULL(clks[idx]))
254 dev_err(dev, "failed to register clock '%s'\n", name);
255 else
256 dev_dbg(dev, "Registered clock '%s'\n", name);
257 clk_data->clk[idx] = sclk;
258 }
259
260 return of_clk_add_provider(np, scpi_of_clk_src_get, clk_data);
261}
262
263static int scpi_clocks_remove(struct platform_device *pdev)
264{
265 struct device *dev = &pdev->dev;
266 struct device_node *child, *np = dev->of_node;
267
268 if (cpufreq_dev) {
269 platform_device_unregister(cpufreq_dev);
270 cpufreq_dev = NULL;
271 }
272
273 for_each_available_child_of_node(np, child)
274 of_clk_del_provider(np);
275 return 0;
276}
277
278static int scpi_clocks_probe(struct platform_device *pdev)
279{
280 int ret;
281 struct device *dev = &pdev->dev;
282 struct device_node *child, *np = dev->of_node;
283 const struct of_device_id *match;
284
285 if (!get_scpi_ops())
286 return -ENXIO;
287
288 for_each_available_child_of_node(np, child) {
289 match = of_match_node(scpi_clk_match, child);
290 if (!match)
291 continue;
292 ret = scpi_clk_add(dev, child, match);
293 if (ret) {
294 scpi_clocks_remove(pdev);
295 return ret;
296 }
297 }
298 /* Add the virtual cpufreq device */
299 cpufreq_dev = platform_device_register_simple("scpi-cpufreq",
300 -1, NULL, 0);
301 if (!cpufreq_dev)
302 pr_warn("unable to register cpufreq device");
303
304 return 0;
305}
306
307static const struct of_device_id scpi_clocks_ids[] = {
308 { .compatible = "arm,scpi-clocks", },
309 {}
310};
311MODULE_DEVICE_TABLE(of, scpi_clocks_ids);
312
313static struct platform_driver scpi_clocks_driver = {
314 .driver = {
315 .name = "scpi_clocks",
316 .of_match_table = scpi_clocks_ids,
317 },
318 .probe = scpi_clocks_probe,
319 .remove = scpi_clocks_remove,
320};
321module_platform_driver(scpi_clocks_driver);
322
323MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
324MODULE_DESCRIPTION("ARM SCPI clock driver");
325MODULE_LICENSE("GPL v2");
diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c
index d28d2fe798d5..6ee91401918e 100644
--- a/drivers/clocksource/tcb_clksrc.c
+++ b/drivers/clocksource/tcb_clksrc.c
@@ -193,10 +193,17 @@ static int __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
193 struct clk *t2_clk = tc->clk[2]; 193 struct clk *t2_clk = tc->clk[2];
194 int irq = tc->irq[2]; 194 int irq = tc->irq[2];
195 195
196 ret = clk_prepare_enable(tc->slow_clk);
197 if (ret)
198 return ret;
199
196 /* try to enable t2 clk to avoid future errors in mode change */ 200 /* try to enable t2 clk to avoid future errors in mode change */
197 ret = clk_prepare_enable(t2_clk); 201 ret = clk_prepare_enable(t2_clk);
198 if (ret) 202 if (ret) {
203 clk_disable_unprepare(tc->slow_clk);
199 return ret; 204 return ret;
205 }
206
200 clk_disable(t2_clk); 207 clk_disable(t2_clk);
201 208
202 clkevt.regs = tc->regs; 209 clkevt.regs = tc->regs;
@@ -208,7 +215,8 @@ static int __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
208 215
209 ret = request_irq(irq, ch2_irq, IRQF_TIMER, "tc_clkevt", &clkevt); 216 ret = request_irq(irq, ch2_irq, IRQF_TIMER, "tc_clkevt", &clkevt);
210 if (ret) { 217 if (ret) {
211 clk_disable_unprepare(t2_clk); 218 clk_unprepare(t2_clk);
219 clk_disable_unprepare(tc->slow_clk);
212 return ret; 220 return ret;
213 } 221 }
214 222
diff --git a/drivers/clocksource/timer-atmel-st.c b/drivers/clocksource/timer-atmel-st.c
index 41b7b6dc1d0d..29d21d68df5a 100644
--- a/drivers/clocksource/timer-atmel-st.c
+++ b/drivers/clocksource/timer-atmel-st.c
@@ -22,6 +22,7 @@
22#include <linux/kernel.h> 22#include <linux/kernel.h>
23#include <linux/interrupt.h> 23#include <linux/interrupt.h>
24#include <linux/irq.h> 24#include <linux/irq.h>
25#include <linux/clk.h>
25#include <linux/clockchips.h> 26#include <linux/clockchips.h>
26#include <linux/export.h> 27#include <linux/export.h>
27#include <linux/mfd/syscon.h> 28#include <linux/mfd/syscon.h>
@@ -33,9 +34,7 @@ static unsigned long last_crtr;
33static u32 irqmask; 34static u32 irqmask;
34static struct clock_event_device clkevt; 35static struct clock_event_device clkevt;
35static struct regmap *regmap_st; 36static struct regmap *regmap_st;
36 37static int timer_latch;
37#define AT91_SLOW_CLOCK 32768
38#define RM9200_TIMER_LATCH ((AT91_SLOW_CLOCK + HZ/2) / HZ)
39 38
40/* 39/*
41 * The ST_CRTR is updated asynchronously to the master clock ... but 40 * The ST_CRTR is updated asynchronously to the master clock ... but
@@ -82,8 +81,8 @@ static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
82 if (sr & AT91_ST_PITS) { 81 if (sr & AT91_ST_PITS) {
83 u32 crtr = read_CRTR(); 82 u32 crtr = read_CRTR();
84 83
85 while (((crtr - last_crtr) & AT91_ST_CRTV) >= RM9200_TIMER_LATCH) { 84 while (((crtr - last_crtr) & AT91_ST_CRTV) >= timer_latch) {
86 last_crtr += RM9200_TIMER_LATCH; 85 last_crtr += timer_latch;
87 clkevt.event_handler(&clkevt); 86 clkevt.event_handler(&clkevt);
88 } 87 }
89 return IRQ_HANDLED; 88 return IRQ_HANDLED;
@@ -144,7 +143,7 @@ static int clkevt32k_set_periodic(struct clock_event_device *dev)
144 143
145 /* PIT for periodic irqs; fixed rate of 1/HZ */ 144 /* PIT for periodic irqs; fixed rate of 1/HZ */
146 irqmask = AT91_ST_PITS; 145 irqmask = AT91_ST_PITS;
147 regmap_write(regmap_st, AT91_ST_PIMR, RM9200_TIMER_LATCH); 146 regmap_write(regmap_st, AT91_ST_PIMR, timer_latch);
148 regmap_write(regmap_st, AT91_ST_IER, irqmask); 147 regmap_write(regmap_st, AT91_ST_IER, irqmask);
149 return 0; 148 return 0;
150} 149}
@@ -197,7 +196,8 @@ static struct clock_event_device clkevt = {
197 */ 196 */
198static void __init atmel_st_timer_init(struct device_node *node) 197static void __init atmel_st_timer_init(struct device_node *node)
199{ 198{
200 unsigned int val; 199 struct clk *sclk;
200 unsigned int sclk_rate, val;
201 int irq, ret; 201 int irq, ret;
202 202
203 regmap_st = syscon_node_to_regmap(node); 203 regmap_st = syscon_node_to_regmap(node);
@@ -221,6 +221,19 @@ static void __init atmel_st_timer_init(struct device_node *node)
221 if (ret) 221 if (ret)
222 panic(pr_fmt("Unable to setup IRQ\n")); 222 panic(pr_fmt("Unable to setup IRQ\n"));
223 223
224 sclk = of_clk_get(node, 0);
225 if (IS_ERR(sclk))
226 panic(pr_fmt("Unable to get slow clock\n"));
227
228 clk_prepare_enable(sclk);
229 if (ret)
230 panic(pr_fmt("Could not enable slow clock\n"));
231
232 sclk_rate = clk_get_rate(sclk);
233 if (!sclk_rate)
234 panic(pr_fmt("Invalid slow clock rate\n"));
235 timer_latch = (sclk_rate + HZ / 2) / HZ;
236
224 /* The 32KiHz "Slow Clock" (tick every 30517.58 nanoseconds) is used 237 /* The 32KiHz "Slow Clock" (tick every 30517.58 nanoseconds) is used
225 * directly for the clocksource and all clockevents, after adjusting 238 * directly for the clocksource and all clockevents, after adjusting
226 * its prescaler from the 1 Hz default. 239 * its prescaler from the 1 Hz default.
@@ -229,11 +242,11 @@ static void __init atmel_st_timer_init(struct device_node *node)
229 242
230 /* Setup timer clockevent, with minimum of two ticks (important!!) */ 243 /* Setup timer clockevent, with minimum of two ticks (important!!) */
231 clkevt.cpumask = cpumask_of(0); 244 clkevt.cpumask = cpumask_of(0);
232 clockevents_config_and_register(&clkevt, AT91_SLOW_CLOCK, 245 clockevents_config_and_register(&clkevt, sclk_rate,
233 2, AT91_ST_ALMV); 246 2, AT91_ST_ALMV);
234 247
235 /* register clocksource */ 248 /* register clocksource */
236 clocksource_register_hz(&clk32k, AT91_SLOW_CLOCK); 249 clocksource_register_hz(&clk32k, sclk_rate);
237} 250}
238CLOCKSOURCE_OF_DECLARE(atmel_st_timer, "atmel,at91rm9200-st", 251CLOCKSOURCE_OF_DECLARE(atmel_st_timer, "atmel,at91rm9200-st",
239 atmel_st_timer_init); 252 atmel_st_timer_init);
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 642fd49793b0..1582c1c016b0 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -199,6 +199,16 @@ config ARM_SA1100_CPUFREQ
199config ARM_SA1110_CPUFREQ 199config ARM_SA1110_CPUFREQ
200 bool 200 bool
201 201
202config ARM_SCPI_CPUFREQ
203 tristate "SCPI based CPUfreq driver"
204 depends on ARM_BIG_LITTLE_CPUFREQ && ARM_SCPI_PROTOCOL
205 help
206 This adds the CPUfreq driver support for ARM big.LITTLE platforms
207 using SCPI protocol for CPU power management.
208
209 This driver uses SCPI Message Protocol driver to interact with the
210 firmware providing the CPU DVFS functionality.
211
202config ARM_SPEAR_CPUFREQ 212config ARM_SPEAR_CPUFREQ
203 bool "SPEAr CPUFreq support" 213 bool "SPEAr CPUFreq support"
204 depends on PLAT_SPEAR 214 depends on PLAT_SPEAR
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index d11309c487d0..c0af1a1281c8 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -71,6 +71,7 @@ obj-$(CONFIG_ARM_S3C64XX_CPUFREQ) += s3c64xx-cpufreq.o
71obj-$(CONFIG_ARM_S5PV210_CPUFREQ) += s5pv210-cpufreq.o 71obj-$(CONFIG_ARM_S5PV210_CPUFREQ) += s5pv210-cpufreq.o
72obj-$(CONFIG_ARM_SA1100_CPUFREQ) += sa1100-cpufreq.o 72obj-$(CONFIG_ARM_SA1100_CPUFREQ) += sa1100-cpufreq.o
73obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o 73obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o
74obj-$(CONFIG_ARM_SCPI_CPUFREQ) += scpi-cpufreq.o
74obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o 75obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o
75obj-$(CONFIG_ARM_TEGRA20_CPUFREQ) += tegra20-cpufreq.o 76obj-$(CONFIG_ARM_TEGRA20_CPUFREQ) += tegra20-cpufreq.o
76obj-$(CONFIG_ARM_TEGRA124_CPUFREQ) += tegra124-cpufreq.o 77obj-$(CONFIG_ARM_TEGRA124_CPUFREQ) += tegra124-cpufreq.o
diff --git a/drivers/cpufreq/scpi-cpufreq.c b/drivers/cpufreq/scpi-cpufreq.c
new file mode 100644
index 000000000000..2c3b16fd3a01
--- /dev/null
+++ b/drivers/cpufreq/scpi-cpufreq.c
@@ -0,0 +1,124 @@
1/*
2 * System Control and Power Interface (SCPI) based CPUFreq Interface driver
3 *
4 * It provides necessary ops to arm_big_little cpufreq driver.
5 *
6 * Copyright (C) 2015 ARM Ltd.
7 * Sudeep Holla <sudeep.holla@arm.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
14 * kind, whether express or implied; without even the implied warranty
15 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
18
19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
21#include <linux/cpufreq.h>
22#include <linux/module.h>
23#include <linux/platform_device.h>
24#include <linux/pm_opp.h>
25#include <linux/scpi_protocol.h>
26#include <linux/types.h>
27
28#include "arm_big_little.h"
29
30static struct scpi_ops *scpi_ops;
31
32static struct scpi_dvfs_info *scpi_get_dvfs_info(struct device *cpu_dev)
33{
34 u8 domain = topology_physical_package_id(cpu_dev->id);
35
36 if (domain < 0)
37 return ERR_PTR(-EINVAL);
38 return scpi_ops->dvfs_get_info(domain);
39}
40
41static int scpi_opp_table_ops(struct device *cpu_dev, bool remove)
42{
43 int idx, ret = 0;
44 struct scpi_opp *opp;
45 struct scpi_dvfs_info *info = scpi_get_dvfs_info(cpu_dev);
46
47 if (IS_ERR(info))
48 return PTR_ERR(info);
49
50 if (!info->opps)
51 return -EIO;
52
53 for (opp = info->opps, idx = 0; idx < info->count; idx++, opp++) {
54 if (remove)
55 dev_pm_opp_remove(cpu_dev, opp->freq);
56 else
57 ret = dev_pm_opp_add(cpu_dev, opp->freq,
58 opp->m_volt * 1000);
59 if (ret) {
60 dev_warn(cpu_dev, "failed to add opp %uHz %umV\n",
61 opp->freq, opp->m_volt);
62 while (idx-- > 0)
63 dev_pm_opp_remove(cpu_dev, (--opp)->freq);
64 return ret;
65 }
66 }
67 return ret;
68}
69
70static int scpi_get_transition_latency(struct device *cpu_dev)
71{
72 struct scpi_dvfs_info *info = scpi_get_dvfs_info(cpu_dev);
73
74 if (IS_ERR(info))
75 return PTR_ERR(info);
76 return info->latency;
77}
78
79static int scpi_init_opp_table(struct device *cpu_dev)
80{
81 return scpi_opp_table_ops(cpu_dev, false);
82}
83
84static void scpi_free_opp_table(struct device *cpu_dev)
85{
86 scpi_opp_table_ops(cpu_dev, true);
87}
88
89static struct cpufreq_arm_bL_ops scpi_cpufreq_ops = {
90 .name = "scpi",
91 .get_transition_latency = scpi_get_transition_latency,
92 .init_opp_table = scpi_init_opp_table,
93 .free_opp_table = scpi_free_opp_table,
94};
95
96static int scpi_cpufreq_probe(struct platform_device *pdev)
97{
98 scpi_ops = get_scpi_ops();
99 if (!scpi_ops)
100 return -EIO;
101
102 return bL_cpufreq_register(&scpi_cpufreq_ops);
103}
104
105static int scpi_cpufreq_remove(struct platform_device *pdev)
106{
107 bL_cpufreq_unregister(&scpi_cpufreq_ops);
108 scpi_ops = NULL;
109 return 0;
110}
111
112static struct platform_driver scpi_cpufreq_platdrv = {
113 .driver = {
114 .name = "scpi-cpufreq",
115 .owner = THIS_MODULE,
116 },
117 .probe = scpi_cpufreq_probe,
118 .remove = scpi_cpufreq_remove,
119};
120module_platform_driver(scpi_cpufreq_platdrv);
121
122MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
123MODULE_DESCRIPTION("ARM SCPI CPUFreq interface driver");
124MODULE_LICENSE("GPL v2");
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 665efca59487..cf478fe6b335 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -8,6 +8,25 @@ menu "Firmware Drivers"
8config ARM_PSCI_FW 8config ARM_PSCI_FW
9 bool 9 bool
10 10
11config ARM_SCPI_PROTOCOL
12 tristate "ARM System Control and Power Interface (SCPI) Message Protocol"
13 depends on ARM_MHU
14 help
15 System Control and Power Interface (SCPI) Message Protocol is
16 defined for the purpose of communication between the Application
17 Cores(AP) and the System Control Processor(SCP). The MHU peripheral
18 provides a mechanism for inter-processor communication between SCP
19 and AP.
20
21 SCP controls most of the power managament on the Application
22 Processors. It offers control and management of: the core/cluster
23 power states, various power domain DVFS including the core/cluster,
24 certain system clocks configuration, thermal sensors and many
25 others.
26
27 This protocol library provides interface for all the client drivers
28 making use of the features offered by the SCP.
29
11config EDD 30config EDD
12 tristate "BIOS Enhanced Disk Drive calls determine boot disk" 31 tristate "BIOS Enhanced Disk Drive calls determine boot disk"
13 depends on X86 32 depends on X86
@@ -135,6 +154,13 @@ config ISCSI_IBFT
135 detect iSCSI boot parameters dynamically during system boot, say Y. 154 detect iSCSI boot parameters dynamically during system boot, say Y.
136 Otherwise, say N. 155 Otherwise, say N.
137 156
157config RASPBERRYPI_FIRMWARE
158 tristate "Raspberry Pi Firmware Driver"
159 depends on BCM2835_MBOX
160 help
161 This option enables support for communicating with the firmware on the
162 Raspberry Pi.
163
138config QCOM_SCM 164config QCOM_SCM
139 bool 165 bool
140 depends on ARM || ARM64 166 depends on ARM || ARM64
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 2ee83474a3c1..48dd4175297e 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -2,6 +2,7 @@
2# Makefile for the linux kernel. 2# Makefile for the linux kernel.
3# 3#
4obj-$(CONFIG_ARM_PSCI_FW) += psci.o 4obj-$(CONFIG_ARM_PSCI_FW) += psci.o
5obj-$(CONFIG_ARM_SCPI_PROTOCOL) += arm_scpi.o
5obj-$(CONFIG_DMI) += dmi_scan.o 6obj-$(CONFIG_DMI) += dmi_scan.o
6obj-$(CONFIG_DMI_SYSFS) += dmi-sysfs.o 7obj-$(CONFIG_DMI_SYSFS) += dmi-sysfs.o
7obj-$(CONFIG_EDD) += edd.o 8obj-$(CONFIG_EDD) += edd.o
@@ -12,10 +13,11 @@ obj-$(CONFIG_DMIID) += dmi-id.o
12obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o 13obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o
13obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o 14obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o
14obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o 15obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o
16obj-$(CONFIG_RASPBERRYPI_FIRMWARE) += raspberrypi.o
15obj-$(CONFIG_QCOM_SCM) += qcom_scm.o 17obj-$(CONFIG_QCOM_SCM) += qcom_scm.o
16obj-$(CONFIG_QCOM_SCM_64) += qcom_scm-64.o 18obj-$(CONFIG_QCOM_SCM_64) += qcom_scm-64.o
17obj-$(CONFIG_QCOM_SCM_32) += qcom_scm-32.o 19obj-$(CONFIG_QCOM_SCM_32) += qcom_scm-32.o
18CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1) 20CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch armv7-a\n.arch_extension sec,-DREQUIRES_SEC=1) -march=armv7-a
19 21
20obj-y += broadcom/ 22obj-y += broadcom/
21obj-$(CONFIG_GOOGLE_FIRMWARE) += google/ 23obj-$(CONFIG_GOOGLE_FIRMWARE) += google/
diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
new file mode 100644
index 000000000000..6174db80c663
--- /dev/null
+++ b/drivers/firmware/arm_scpi.c
@@ -0,0 +1,771 @@
1/*
2 * System Control and Power Interface (SCPI) Message Protocol driver
3 *
4 * SCPI Message Protocol is used between the System Control Processor(SCP)
5 * and the Application Processors(AP). The Message Handling Unit(MHU)
6 * provides a mechanism for inter-processor communication between SCP's
7 * Cortex M3 and AP.
8 *
9 * SCP offers control and management of the core/cluster power states,
10 * various power domain DVFS including the core/cluster, certain system
11 * clocks configuration, thermal sensors and many others.
12 *
13 * Copyright (C) 2015 ARM Ltd.
14 *
15 * This program is free software; you can redistribute it and/or modify it
16 * under the terms and conditions of the GNU General Public License,
17 * version 2, as published by the Free Software Foundation.
18 *
19 * This program is distributed in the hope it will be useful, but WITHOUT
20 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
22 * more details.
23 *
24 * You should have received a copy of the GNU General Public License along
25 * with this program. If not, see <http://www.gnu.org/licenses/>.
26 */
27
28#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
29
30#include <linux/bitmap.h>
31#include <linux/device.h>
32#include <linux/err.h>
33#include <linux/export.h>
34#include <linux/io.h>
35#include <linux/kernel.h>
36#include <linux/list.h>
37#include <linux/mailbox_client.h>
38#include <linux/module.h>
39#include <linux/of_address.h>
40#include <linux/of_platform.h>
41#include <linux/printk.h>
42#include <linux/scpi_protocol.h>
43#include <linux/slab.h>
44#include <linux/sort.h>
45#include <linux/spinlock.h>
46
47#define CMD_ID_SHIFT 0
48#define CMD_ID_MASK 0x7f
49#define CMD_TOKEN_ID_SHIFT 8
50#define CMD_TOKEN_ID_MASK 0xff
51#define CMD_DATA_SIZE_SHIFT 16
52#define CMD_DATA_SIZE_MASK 0x1ff
53#define PACK_SCPI_CMD(cmd_id, tx_sz) \
54 ((((cmd_id) & CMD_ID_MASK) << CMD_ID_SHIFT) | \
55 (((tx_sz) & CMD_DATA_SIZE_MASK) << CMD_DATA_SIZE_SHIFT))
56#define ADD_SCPI_TOKEN(cmd, token) \
57 ((cmd) |= (((token) & CMD_TOKEN_ID_MASK) << CMD_TOKEN_ID_SHIFT))
58
59#define CMD_SIZE(cmd) (((cmd) >> CMD_DATA_SIZE_SHIFT) & CMD_DATA_SIZE_MASK)
60#define CMD_UNIQ_MASK (CMD_TOKEN_ID_MASK << CMD_TOKEN_ID_SHIFT | CMD_ID_MASK)
61#define CMD_XTRACT_UNIQ(cmd) ((cmd) & CMD_UNIQ_MASK)
62
63#define SCPI_SLOT 0
64
65#define MAX_DVFS_DOMAINS 8
66#define MAX_DVFS_OPPS 8
67#define DVFS_LATENCY(hdr) (le32_to_cpu(hdr) >> 16)
68#define DVFS_OPP_COUNT(hdr) ((le32_to_cpu(hdr) >> 8) & 0xff)
69
70#define PROTOCOL_REV_MINOR_BITS 16
71#define PROTOCOL_REV_MINOR_MASK ((1U << PROTOCOL_REV_MINOR_BITS) - 1)
72#define PROTOCOL_REV_MAJOR(x) ((x) >> PROTOCOL_REV_MINOR_BITS)
73#define PROTOCOL_REV_MINOR(x) ((x) & PROTOCOL_REV_MINOR_MASK)
74
75#define FW_REV_MAJOR_BITS 24
76#define FW_REV_MINOR_BITS 16
77#define FW_REV_PATCH_MASK ((1U << FW_REV_MINOR_BITS) - 1)
78#define FW_REV_MINOR_MASK ((1U << FW_REV_MAJOR_BITS) - 1)
79#define FW_REV_MAJOR(x) ((x) >> FW_REV_MAJOR_BITS)
80#define FW_REV_MINOR(x) (((x) & FW_REV_MINOR_MASK) >> FW_REV_MINOR_BITS)
81#define FW_REV_PATCH(x) ((x) & FW_REV_PATCH_MASK)
82
83#define MAX_RX_TIMEOUT (msecs_to_jiffies(20))
84
85enum scpi_error_codes {
86 SCPI_SUCCESS = 0, /* Success */
87 SCPI_ERR_PARAM = 1, /* Invalid parameter(s) */
88 SCPI_ERR_ALIGN = 2, /* Invalid alignment */
89 SCPI_ERR_SIZE = 3, /* Invalid size */
90 SCPI_ERR_HANDLER = 4, /* Invalid handler/callback */
91 SCPI_ERR_ACCESS = 5, /* Invalid access/permission denied */
92 SCPI_ERR_RANGE = 6, /* Value out of range */
93 SCPI_ERR_TIMEOUT = 7, /* Timeout has occurred */
94 SCPI_ERR_NOMEM = 8, /* Invalid memory area or pointer */
95 SCPI_ERR_PWRSTATE = 9, /* Invalid power state */
96 SCPI_ERR_SUPPORT = 10, /* Not supported or disabled */
97 SCPI_ERR_DEVICE = 11, /* Device error */
98 SCPI_ERR_BUSY = 12, /* Device busy */
99 SCPI_ERR_MAX
100};
101
102enum scpi_std_cmd {
103 SCPI_CMD_INVALID = 0x00,
104 SCPI_CMD_SCPI_READY = 0x01,
105 SCPI_CMD_SCPI_CAPABILITIES = 0x02,
106 SCPI_CMD_SET_CSS_PWR_STATE = 0x03,
107 SCPI_CMD_GET_CSS_PWR_STATE = 0x04,
108 SCPI_CMD_SET_SYS_PWR_STATE = 0x05,
109 SCPI_CMD_SET_CPU_TIMER = 0x06,
110 SCPI_CMD_CANCEL_CPU_TIMER = 0x07,
111 SCPI_CMD_DVFS_CAPABILITIES = 0x08,
112 SCPI_CMD_GET_DVFS_INFO = 0x09,
113 SCPI_CMD_SET_DVFS = 0x0a,
114 SCPI_CMD_GET_DVFS = 0x0b,
115 SCPI_CMD_GET_DVFS_STAT = 0x0c,
116 SCPI_CMD_CLOCK_CAPABILITIES = 0x0d,
117 SCPI_CMD_GET_CLOCK_INFO = 0x0e,
118 SCPI_CMD_SET_CLOCK_VALUE = 0x0f,
119 SCPI_CMD_GET_CLOCK_VALUE = 0x10,
120 SCPI_CMD_PSU_CAPABILITIES = 0x11,
121 SCPI_CMD_GET_PSU_INFO = 0x12,
122 SCPI_CMD_SET_PSU = 0x13,
123 SCPI_CMD_GET_PSU = 0x14,
124 SCPI_CMD_SENSOR_CAPABILITIES = 0x15,
125 SCPI_CMD_SENSOR_INFO = 0x16,
126 SCPI_CMD_SENSOR_VALUE = 0x17,
127 SCPI_CMD_SENSOR_CFG_PERIODIC = 0x18,
128 SCPI_CMD_SENSOR_CFG_BOUNDS = 0x19,
129 SCPI_CMD_SENSOR_ASYNC_VALUE = 0x1a,
130 SCPI_CMD_SET_DEVICE_PWR_STATE = 0x1b,
131 SCPI_CMD_GET_DEVICE_PWR_STATE = 0x1c,
132 SCPI_CMD_COUNT
133};
134
135struct scpi_xfer {
136 u32 slot; /* has to be first element */
137 u32 cmd;
138 u32 status;
139 const void *tx_buf;
140 void *rx_buf;
141 unsigned int tx_len;
142 unsigned int rx_len;
143 struct list_head node;
144 struct completion done;
145};
146
147struct scpi_chan {
148 struct mbox_client cl;
149 struct mbox_chan *chan;
150 void __iomem *tx_payload;
151 void __iomem *rx_payload;
152 struct list_head rx_pending;
153 struct list_head xfers_list;
154 struct scpi_xfer *xfers;
155 spinlock_t rx_lock; /* locking for the rx pending list */
156 struct mutex xfers_lock;
157 u8 token;
158};
159
160struct scpi_drvinfo {
161 u32 protocol_version;
162 u32 firmware_version;
163 int num_chans;
164 atomic_t next_chan;
165 struct scpi_ops *scpi_ops;
166 struct scpi_chan *channels;
167 struct scpi_dvfs_info *dvfs[MAX_DVFS_DOMAINS];
168};
169
170/*
171 * The SCP firmware only executes in little-endian mode, so any buffers
172 * shared through SCPI should have their contents converted to little-endian
173 */
174struct scpi_shared_mem {
175 __le32 command;
176 __le32 status;
177 u8 payload[0];
178} __packed;
179
180struct scp_capabilities {
181 __le32 protocol_version;
182 __le32 event_version;
183 __le32 platform_version;
184 __le32 commands[4];
185} __packed;
186
187struct clk_get_info {
188 __le16 id;
189 __le16 flags;
190 __le32 min_rate;
191 __le32 max_rate;
192 u8 name[20];
193} __packed;
194
195struct clk_get_value {
196 __le32 rate;
197} __packed;
198
199struct clk_set_value {
200 __le16 id;
201 __le16 reserved;
202 __le32 rate;
203} __packed;
204
205struct dvfs_info {
206 __le32 header;
207 struct {
208 __le32 freq;
209 __le32 m_volt;
210 } opps[MAX_DVFS_OPPS];
211} __packed;
212
213struct dvfs_get {
214 u8 index;
215} __packed;
216
217struct dvfs_set {
218 u8 domain;
219 u8 index;
220} __packed;
221
222struct sensor_capabilities {
223 __le16 sensors;
224} __packed;
225
226struct _scpi_sensor_info {
227 __le16 sensor_id;
228 u8 class;
229 u8 trigger_type;
230 char name[20];
231};
232
233struct sensor_value {
234 __le32 val;
235} __packed;
236
237static struct scpi_drvinfo *scpi_info;
238
239static int scpi_linux_errmap[SCPI_ERR_MAX] = {
240 /* better than switch case as long as return value is continuous */
241 0, /* SCPI_SUCCESS */
242 -EINVAL, /* SCPI_ERR_PARAM */
243 -ENOEXEC, /* SCPI_ERR_ALIGN */
244 -EMSGSIZE, /* SCPI_ERR_SIZE */
245 -EINVAL, /* SCPI_ERR_HANDLER */
246 -EACCES, /* SCPI_ERR_ACCESS */
247 -ERANGE, /* SCPI_ERR_RANGE */
248 -ETIMEDOUT, /* SCPI_ERR_TIMEOUT */
249 -ENOMEM, /* SCPI_ERR_NOMEM */
250 -EINVAL, /* SCPI_ERR_PWRSTATE */
251 -EOPNOTSUPP, /* SCPI_ERR_SUPPORT */
252 -EIO, /* SCPI_ERR_DEVICE */
253 -EBUSY, /* SCPI_ERR_BUSY */
254};
255
256static inline int scpi_to_linux_errno(int errno)
257{
258 if (errno >= SCPI_SUCCESS && errno < SCPI_ERR_MAX)
259 return scpi_linux_errmap[errno];
260 return -EIO;
261}
262
263static void scpi_process_cmd(struct scpi_chan *ch, u32 cmd)
264{
265 unsigned long flags;
266 struct scpi_xfer *t, *match = NULL;
267
268 spin_lock_irqsave(&ch->rx_lock, flags);
269 if (list_empty(&ch->rx_pending)) {
270 spin_unlock_irqrestore(&ch->rx_lock, flags);
271 return;
272 }
273
274 list_for_each_entry(t, &ch->rx_pending, node)
275 if (CMD_XTRACT_UNIQ(t->cmd) == CMD_XTRACT_UNIQ(cmd)) {
276 list_del(&t->node);
277 match = t;
278 break;
279 }
280 /* check if wait_for_completion is in progress or timed-out */
281 if (match && !completion_done(&match->done)) {
282 struct scpi_shared_mem *mem = ch->rx_payload;
283 unsigned int len = min(match->rx_len, CMD_SIZE(cmd));
284
285 match->status = le32_to_cpu(mem->status);
286 memcpy_fromio(match->rx_buf, mem->payload, len);
287 if (match->rx_len > len)
288 memset(match->rx_buf + len, 0, match->rx_len - len);
289 complete(&match->done);
290 }
291 spin_unlock_irqrestore(&ch->rx_lock, flags);
292}
293
294static void scpi_handle_remote_msg(struct mbox_client *c, void *msg)
295{
296 struct scpi_chan *ch = container_of(c, struct scpi_chan, cl);
297 struct scpi_shared_mem *mem = ch->rx_payload;
298 u32 cmd = le32_to_cpu(mem->command);
299
300 scpi_process_cmd(ch, cmd);
301}
302
303static void scpi_tx_prepare(struct mbox_client *c, void *msg)
304{
305 unsigned long flags;
306 struct scpi_xfer *t = msg;
307 struct scpi_chan *ch = container_of(c, struct scpi_chan, cl);
308 struct scpi_shared_mem *mem = (struct scpi_shared_mem *)ch->tx_payload;
309
310 if (t->tx_buf)
311 memcpy_toio(mem->payload, t->tx_buf, t->tx_len);
312 if (t->rx_buf) {
313 if (!(++ch->token))
314 ++ch->token;
315 ADD_SCPI_TOKEN(t->cmd, ch->token);
316 spin_lock_irqsave(&ch->rx_lock, flags);
317 list_add_tail(&t->node, &ch->rx_pending);
318 spin_unlock_irqrestore(&ch->rx_lock, flags);
319 }
320 mem->command = cpu_to_le32(t->cmd);
321}
322
323static struct scpi_xfer *get_scpi_xfer(struct scpi_chan *ch)
324{
325 struct scpi_xfer *t;
326
327 mutex_lock(&ch->xfers_lock);
328 if (list_empty(&ch->xfers_list)) {
329 mutex_unlock(&ch->xfers_lock);
330 return NULL;
331 }
332 t = list_first_entry(&ch->xfers_list, struct scpi_xfer, node);
333 list_del(&t->node);
334 mutex_unlock(&ch->xfers_lock);
335 return t;
336}
337
338static void put_scpi_xfer(struct scpi_xfer *t, struct scpi_chan *ch)
339{
340 mutex_lock(&ch->xfers_lock);
341 list_add_tail(&t->node, &ch->xfers_list);
342 mutex_unlock(&ch->xfers_lock);
343}
344
345static int scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
346 void *rx_buf, unsigned int rx_len)
347{
348 int ret;
349 u8 chan;
350 struct scpi_xfer *msg;
351 struct scpi_chan *scpi_chan;
352
353 chan = atomic_inc_return(&scpi_info->next_chan) % scpi_info->num_chans;
354 scpi_chan = scpi_info->channels + chan;
355
356 msg = get_scpi_xfer(scpi_chan);
357 if (!msg)
358 return -ENOMEM;
359
360 msg->slot = BIT(SCPI_SLOT);
361 msg->cmd = PACK_SCPI_CMD(cmd, tx_len);
362 msg->tx_buf = tx_buf;
363 msg->tx_len = tx_len;
364 msg->rx_buf = rx_buf;
365 msg->rx_len = rx_len;
366 init_completion(&msg->done);
367
368 ret = mbox_send_message(scpi_chan->chan, msg);
369 if (ret < 0 || !rx_buf)
370 goto out;
371
372 if (!wait_for_completion_timeout(&msg->done, MAX_RX_TIMEOUT))
373 ret = -ETIMEDOUT;
374 else
375 /* first status word */
376 ret = le32_to_cpu(msg->status);
377out:
378 if (ret < 0 && rx_buf) /* remove entry from the list if timed-out */
379 scpi_process_cmd(scpi_chan, msg->cmd);
380
381 put_scpi_xfer(msg, scpi_chan);
382 /* SCPI error codes > 0, translate them to Linux scale*/
383 return ret > 0 ? scpi_to_linux_errno(ret) : ret;
384}
385
386static u32 scpi_get_version(void)
387{
388 return scpi_info->protocol_version;
389}
390
391static int
392scpi_clk_get_range(u16 clk_id, unsigned long *min, unsigned long *max)
393{
394 int ret;
395 struct clk_get_info clk;
396 __le16 le_clk_id = cpu_to_le16(clk_id);
397
398 ret = scpi_send_message(SCPI_CMD_GET_CLOCK_INFO, &le_clk_id,
399 sizeof(le_clk_id), &clk, sizeof(clk));
400 if (!ret) {
401 *min = le32_to_cpu(clk.min_rate);
402 *max = le32_to_cpu(clk.max_rate);
403 }
404 return ret;
405}
406
407static unsigned long scpi_clk_get_val(u16 clk_id)
408{
409 int ret;
410 struct clk_get_value clk;
411 __le16 le_clk_id = cpu_to_le16(clk_id);
412
413 ret = scpi_send_message(SCPI_CMD_GET_CLOCK_VALUE, &le_clk_id,
414 sizeof(le_clk_id), &clk, sizeof(clk));
415 return ret ? ret : le32_to_cpu(clk.rate);
416}
417
418static int scpi_clk_set_val(u16 clk_id, unsigned long rate)
419{
420 int stat;
421 struct clk_set_value clk = {
422 .id = cpu_to_le16(clk_id),
423 .rate = cpu_to_le32(rate)
424 };
425
426 return scpi_send_message(SCPI_CMD_SET_CLOCK_VALUE, &clk, sizeof(clk),
427 &stat, sizeof(stat));
428}
429
430static int scpi_dvfs_get_idx(u8 domain)
431{
432 int ret;
433 struct dvfs_get dvfs;
434
435 ret = scpi_send_message(SCPI_CMD_GET_DVFS, &domain, sizeof(domain),
436 &dvfs, sizeof(dvfs));
437 return ret ? ret : dvfs.index;
438}
439
440static int scpi_dvfs_set_idx(u8 domain, u8 index)
441{
442 int stat;
443 struct dvfs_set dvfs = {domain, index};
444
445 return scpi_send_message(SCPI_CMD_SET_DVFS, &dvfs, sizeof(dvfs),
446 &stat, sizeof(stat));
447}
448
449static int opp_cmp_func(const void *opp1, const void *opp2)
450{
451 const struct scpi_opp *t1 = opp1, *t2 = opp2;
452
453 return t1->freq - t2->freq;
454}
455
456static struct scpi_dvfs_info *scpi_dvfs_get_info(u8 domain)
457{
458 struct scpi_dvfs_info *info;
459 struct scpi_opp *opp;
460 struct dvfs_info buf;
461 int ret, i;
462
463 if (domain >= MAX_DVFS_DOMAINS)
464 return ERR_PTR(-EINVAL);
465
466 if (scpi_info->dvfs[domain]) /* data already populated */
467 return scpi_info->dvfs[domain];
468
469 ret = scpi_send_message(SCPI_CMD_GET_DVFS_INFO, &domain, sizeof(domain),
470 &buf, sizeof(buf));
471
472 if (ret)
473 return ERR_PTR(ret);
474
475 info = kmalloc(sizeof(*info), GFP_KERNEL);
476 if (!info)
477 return ERR_PTR(-ENOMEM);
478
479 info->count = DVFS_OPP_COUNT(buf.header);
480 info->latency = DVFS_LATENCY(buf.header) * 1000; /* uS to nS */
481
482 info->opps = kcalloc(info->count, sizeof(*opp), GFP_KERNEL);
483 if (!info->opps) {
484 kfree(info);
485 return ERR_PTR(-ENOMEM);
486 }
487
488 for (i = 0, opp = info->opps; i < info->count; i++, opp++) {
489 opp->freq = le32_to_cpu(buf.opps[i].freq);
490 opp->m_volt = le32_to_cpu(buf.opps[i].m_volt);
491 }
492
493 sort(info->opps, info->count, sizeof(*opp), opp_cmp_func, NULL);
494
495 scpi_info->dvfs[domain] = info;
496 return info;
497}
498
499static int scpi_sensor_get_capability(u16 *sensors)
500{
501 struct sensor_capabilities cap_buf;
502 int ret;
503
504 ret = scpi_send_message(SCPI_CMD_SENSOR_CAPABILITIES, NULL, 0, &cap_buf,
505 sizeof(cap_buf));
506 if (!ret)
507 *sensors = le16_to_cpu(cap_buf.sensors);
508
509 return ret;
510}
511
512static int scpi_sensor_get_info(u16 sensor_id, struct scpi_sensor_info *info)
513{
514 __le16 id = cpu_to_le16(sensor_id);
515 struct _scpi_sensor_info _info;
516 int ret;
517
518 ret = scpi_send_message(SCPI_CMD_SENSOR_INFO, &id, sizeof(id),
519 &_info, sizeof(_info));
520 if (!ret) {
521 memcpy(info, &_info, sizeof(*info));
522 info->sensor_id = le16_to_cpu(_info.sensor_id);
523 }
524
525 return ret;
526}
527
528int scpi_sensor_get_value(u16 sensor, u32 *val)
529{
530 struct sensor_value buf;
531 int ret;
532
533 ret = scpi_send_message(SCPI_CMD_SENSOR_VALUE, &sensor, sizeof(sensor),
534 &buf, sizeof(buf));
535 if (!ret)
536 *val = le32_to_cpu(buf.val);
537
538 return ret;
539}
540
541static struct scpi_ops scpi_ops = {
542 .get_version = scpi_get_version,
543 .clk_get_range = scpi_clk_get_range,
544 .clk_get_val = scpi_clk_get_val,
545 .clk_set_val = scpi_clk_set_val,
546 .dvfs_get_idx = scpi_dvfs_get_idx,
547 .dvfs_set_idx = scpi_dvfs_set_idx,
548 .dvfs_get_info = scpi_dvfs_get_info,
549 .sensor_get_capability = scpi_sensor_get_capability,
550 .sensor_get_info = scpi_sensor_get_info,
551 .sensor_get_value = scpi_sensor_get_value,
552};
553
554struct scpi_ops *get_scpi_ops(void)
555{
556 return scpi_info ? scpi_info->scpi_ops : NULL;
557}
558EXPORT_SYMBOL_GPL(get_scpi_ops);
559
560static int scpi_init_versions(struct scpi_drvinfo *info)
561{
562 int ret;
563 struct scp_capabilities caps;
564
565 ret = scpi_send_message(SCPI_CMD_SCPI_CAPABILITIES, NULL, 0,
566 &caps, sizeof(caps));
567 if (!ret) {
568 info->protocol_version = le32_to_cpu(caps.protocol_version);
569 info->firmware_version = le32_to_cpu(caps.platform_version);
570 }
571 return ret;
572}
573
574static ssize_t protocol_version_show(struct device *dev,
575 struct device_attribute *attr, char *buf)
576{
577 struct scpi_drvinfo *scpi_info = dev_get_drvdata(dev);
578
579 return sprintf(buf, "%d.%d\n",
580 PROTOCOL_REV_MAJOR(scpi_info->protocol_version),
581 PROTOCOL_REV_MINOR(scpi_info->protocol_version));
582}
583static DEVICE_ATTR_RO(protocol_version);
584
585static ssize_t firmware_version_show(struct device *dev,
586 struct device_attribute *attr, char *buf)
587{
588 struct scpi_drvinfo *scpi_info = dev_get_drvdata(dev);
589
590 return sprintf(buf, "%d.%d.%d\n",
591 FW_REV_MAJOR(scpi_info->firmware_version),
592 FW_REV_MINOR(scpi_info->firmware_version),
593 FW_REV_PATCH(scpi_info->firmware_version));
594}
595static DEVICE_ATTR_RO(firmware_version);
596
597static struct attribute *versions_attrs[] = {
598 &dev_attr_firmware_version.attr,
599 &dev_attr_protocol_version.attr,
600 NULL,
601};
602ATTRIBUTE_GROUPS(versions);
603
604static void
605scpi_free_channels(struct device *dev, struct scpi_chan *pchan, int count)
606{
607 int i;
608
609 for (i = 0; i < count && pchan->chan; i++, pchan++) {
610 mbox_free_channel(pchan->chan);
611 devm_kfree(dev, pchan->xfers);
612 devm_iounmap(dev, pchan->rx_payload);
613 }
614}
615
616static int scpi_remove(struct platform_device *pdev)
617{
618 int i;
619 struct device *dev = &pdev->dev;
620 struct scpi_drvinfo *info = platform_get_drvdata(pdev);
621
622 scpi_info = NULL; /* stop exporting SCPI ops through get_scpi_ops */
623
624 of_platform_depopulate(dev);
625 sysfs_remove_groups(&dev->kobj, versions_groups);
626 scpi_free_channels(dev, info->channels, info->num_chans);
627 platform_set_drvdata(pdev, NULL);
628
629 for (i = 0; i < MAX_DVFS_DOMAINS && info->dvfs[i]; i++) {
630 kfree(info->dvfs[i]->opps);
631 kfree(info->dvfs[i]);
632 }
633 devm_kfree(dev, info->channels);
634 devm_kfree(dev, info);
635
636 return 0;
637}
638
639#define MAX_SCPI_XFERS 10
640static int scpi_alloc_xfer_list(struct device *dev, struct scpi_chan *ch)
641{
642 int i;
643 struct scpi_xfer *xfers;
644
645 xfers = devm_kzalloc(dev, MAX_SCPI_XFERS * sizeof(*xfers), GFP_KERNEL);
646 if (!xfers)
647 return -ENOMEM;
648
649 ch->xfers = xfers;
650 for (i = 0; i < MAX_SCPI_XFERS; i++, xfers++)
651 list_add_tail(&xfers->node, &ch->xfers_list);
652 return 0;
653}
654
655static int scpi_probe(struct platform_device *pdev)
656{
657 int count, idx, ret;
658 struct resource res;
659 struct scpi_chan *scpi_chan;
660 struct device *dev = &pdev->dev;
661 struct device_node *np = dev->of_node;
662
663 scpi_info = devm_kzalloc(dev, sizeof(*scpi_info), GFP_KERNEL);
664 if (!scpi_info)
665 return -ENOMEM;
666
667 count = of_count_phandle_with_args(np, "mboxes", "#mbox-cells");
668 if (count < 0) {
669 dev_err(dev, "no mboxes property in '%s'\n", np->full_name);
670 return -ENODEV;
671 }
672
673 scpi_chan = devm_kcalloc(dev, count, sizeof(*scpi_chan), GFP_KERNEL);
674 if (!scpi_chan)
675 return -ENOMEM;
676
677 for (idx = 0; idx < count; idx++) {
678 resource_size_t size;
679 struct scpi_chan *pchan = scpi_chan + idx;
680 struct mbox_client *cl = &pchan->cl;
681 struct device_node *shmem = of_parse_phandle(np, "shmem", idx);
682
683 if (of_address_to_resource(shmem, 0, &res)) {
684 dev_err(dev, "failed to get SCPI payload mem resource\n");
685 ret = -EINVAL;
686 goto err;
687 }
688
689 size = resource_size(&res);
690 pchan->rx_payload = devm_ioremap(dev, res.start, size);
691 if (!pchan->rx_payload) {
692 dev_err(dev, "failed to ioremap SCPI payload\n");
693 ret = -EADDRNOTAVAIL;
694 goto err;
695 }
696 pchan->tx_payload = pchan->rx_payload + (size >> 1);
697
698 cl->dev = dev;
699 cl->rx_callback = scpi_handle_remote_msg;
700 cl->tx_prepare = scpi_tx_prepare;
701 cl->tx_block = true;
702 cl->tx_tout = 50;
703 cl->knows_txdone = false; /* controller can't ack */
704
705 INIT_LIST_HEAD(&pchan->rx_pending);
706 INIT_LIST_HEAD(&pchan->xfers_list);
707 spin_lock_init(&pchan->rx_lock);
708 mutex_init(&pchan->xfers_lock);
709
710 ret = scpi_alloc_xfer_list(dev, pchan);
711 if (!ret) {
712 pchan->chan = mbox_request_channel(cl, idx);
713 if (!IS_ERR(pchan->chan))
714 continue;
715 ret = PTR_ERR(pchan->chan);
716 if (ret != -EPROBE_DEFER)
717 dev_err(dev, "failed to get channel%d err %d\n",
718 idx, ret);
719 }
720err:
721 scpi_free_channels(dev, scpi_chan, idx);
722 scpi_info = NULL;
723 return ret;
724 }
725
726 scpi_info->channels = scpi_chan;
727 scpi_info->num_chans = count;
728 platform_set_drvdata(pdev, scpi_info);
729
730 ret = scpi_init_versions(scpi_info);
731 if (ret) {
732 dev_err(dev, "incorrect or no SCP firmware found\n");
733 scpi_remove(pdev);
734 return ret;
735 }
736
737 _dev_info(dev, "SCP Protocol %d.%d Firmware %d.%d.%d version\n",
738 PROTOCOL_REV_MAJOR(scpi_info->protocol_version),
739 PROTOCOL_REV_MINOR(scpi_info->protocol_version),
740 FW_REV_MAJOR(scpi_info->firmware_version),
741 FW_REV_MINOR(scpi_info->firmware_version),
742 FW_REV_PATCH(scpi_info->firmware_version));
743 scpi_info->scpi_ops = &scpi_ops;
744
745 ret = sysfs_create_groups(&dev->kobj, versions_groups);
746 if (ret)
747 dev_err(dev, "unable to create sysfs version group\n");
748
749 return of_platform_populate(dev->of_node, NULL, NULL, dev);
750}
751
752static const struct of_device_id scpi_of_match[] = {
753 {.compatible = "arm,scpi"},
754 {},
755};
756
757MODULE_DEVICE_TABLE(of, scpi_of_match);
758
759static struct platform_driver scpi_driver = {
760 .driver = {
761 .name = "scpi_protocol",
762 .of_match_table = scpi_of_match,
763 },
764 .probe = scpi_probe,
765 .remove = scpi_remove,
766};
767module_platform_driver(scpi_driver);
768
769MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
770MODULE_DESCRIPTION("ARM SCPI mailbox protocol driver");
771MODULE_LICENSE("GPL v2");
diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
index 42700f09a8c5..d24f35d74b27 100644
--- a/drivers/firmware/psci.c
+++ b/drivers/firmware/psci.c
@@ -20,23 +20,25 @@
20#include <linux/printk.h> 20#include <linux/printk.h>
21#include <linux/psci.h> 21#include <linux/psci.h>
22#include <linux/reboot.h> 22#include <linux/reboot.h>
23#include <linux/suspend.h>
23 24
24#include <uapi/linux/psci.h> 25#include <uapi/linux/psci.h>
25 26
26#include <asm/cputype.h> 27#include <asm/cputype.h>
27#include <asm/system_misc.h> 28#include <asm/system_misc.h>
28#include <asm/smp_plat.h> 29#include <asm/smp_plat.h>
30#include <asm/suspend.h>
29 31
30/* 32/*
31 * While a 64-bit OS can make calls with SMC32 calling conventions, for some 33 * While a 64-bit OS can make calls with SMC32 calling conventions, for some
32 * calls it is necessary to use SMC64 to pass or return 64-bit values. For such 34 * calls it is necessary to use SMC64 to pass or return 64-bit values.
33 * calls PSCI_0_2_FN_NATIVE(x) will choose the appropriate (native-width) 35 * For such calls PSCI_FN_NATIVE(version, name) will choose the appropriate
34 * function ID. 36 * (native-width) function ID.
35 */ 37 */
36#ifdef CONFIG_64BIT 38#ifdef CONFIG_64BIT
37#define PSCI_0_2_FN_NATIVE(name) PSCI_0_2_FN64_##name 39#define PSCI_FN_NATIVE(version, name) PSCI_##version##_FN64_##name
38#else 40#else
39#define PSCI_0_2_FN_NATIVE(name) PSCI_0_2_FN_##name 41#define PSCI_FN_NATIVE(version, name) PSCI_##version##_FN_##name
40#endif 42#endif
41 43
42/* 44/*
@@ -70,6 +72,41 @@ enum psci_function {
70 72
71static u32 psci_function_id[PSCI_FN_MAX]; 73static u32 psci_function_id[PSCI_FN_MAX];
72 74
75#define PSCI_0_2_POWER_STATE_MASK \
76 (PSCI_0_2_POWER_STATE_ID_MASK | \
77 PSCI_0_2_POWER_STATE_TYPE_MASK | \
78 PSCI_0_2_POWER_STATE_AFFL_MASK)
79
80#define PSCI_1_0_EXT_POWER_STATE_MASK \
81 (PSCI_1_0_EXT_POWER_STATE_ID_MASK | \
82 PSCI_1_0_EXT_POWER_STATE_TYPE_MASK)
83
84static u32 psci_cpu_suspend_feature;
85
86static inline bool psci_has_ext_power_state(void)
87{
88 return psci_cpu_suspend_feature &
89 PSCI_1_0_FEATURES_CPU_SUSPEND_PF_MASK;
90}
91
92bool psci_power_state_loses_context(u32 state)
93{
94 const u32 mask = psci_has_ext_power_state() ?
95 PSCI_1_0_EXT_POWER_STATE_TYPE_MASK :
96 PSCI_0_2_POWER_STATE_TYPE_MASK;
97
98 return state & mask;
99}
100
101bool psci_power_state_is_valid(u32 state)
102{
103 const u32 valid_mask = psci_has_ext_power_state() ?
104 PSCI_1_0_EXT_POWER_STATE_MASK :
105 PSCI_0_2_POWER_STATE_MASK;
106
107 return !(state & ~valid_mask);
108}
109
73static int psci_to_linux_errno(int errno) 110static int psci_to_linux_errno(int errno)
74{ 111{
75 switch (errno) { 112 switch (errno) {
@@ -78,6 +115,7 @@ static int psci_to_linux_errno(int errno)
78 case PSCI_RET_NOT_SUPPORTED: 115 case PSCI_RET_NOT_SUPPORTED:
79 return -EOPNOTSUPP; 116 return -EOPNOTSUPP;
80 case PSCI_RET_INVALID_PARAMS: 117 case PSCI_RET_INVALID_PARAMS:
118 case PSCI_RET_INVALID_ADDRESS:
81 return -EINVAL; 119 return -EINVAL;
82 case PSCI_RET_DENIED: 120 case PSCI_RET_DENIED:
83 return -EPERM; 121 return -EPERM;
@@ -134,7 +172,7 @@ static int psci_migrate(unsigned long cpuid)
134static int psci_affinity_info(unsigned long target_affinity, 172static int psci_affinity_info(unsigned long target_affinity,
135 unsigned long lowest_affinity_level) 173 unsigned long lowest_affinity_level)
136{ 174{
137 return invoke_psci_fn(PSCI_0_2_FN_NATIVE(AFFINITY_INFO), 175 return invoke_psci_fn(PSCI_FN_NATIVE(0_2, AFFINITY_INFO),
138 target_affinity, lowest_affinity_level, 0); 176 target_affinity, lowest_affinity_level, 0);
139} 177}
140 178
@@ -145,7 +183,7 @@ static int psci_migrate_info_type(void)
145 183
146static unsigned long psci_migrate_info_up_cpu(void) 184static unsigned long psci_migrate_info_up_cpu(void)
147{ 185{
148 return invoke_psci_fn(PSCI_0_2_FN_NATIVE(MIGRATE_INFO_UP_CPU), 186 return invoke_psci_fn(PSCI_FN_NATIVE(0_2, MIGRATE_INFO_UP_CPU),
149 0, 0, 0); 187 0, 0, 0);
150} 188}
151 189
@@ -181,6 +219,49 @@ static void psci_sys_poweroff(void)
181 invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0); 219 invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
182} 220}
183 221
222static int __init psci_features(u32 psci_func_id)
223{
224 return invoke_psci_fn(PSCI_1_0_FN_PSCI_FEATURES,
225 psci_func_id, 0, 0);
226}
227
228static int psci_system_suspend(unsigned long unused)
229{
230 return invoke_psci_fn(PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND),
231 virt_to_phys(cpu_resume), 0, 0);
232}
233
234static int psci_system_suspend_enter(suspend_state_t state)
235{
236 return cpu_suspend(0, psci_system_suspend);
237}
238
239static const struct platform_suspend_ops psci_suspend_ops = {
240 .valid = suspend_valid_only_mem,
241 .enter = psci_system_suspend_enter,
242};
243
244static void __init psci_init_system_suspend(void)
245{
246 int ret;
247
248 if (!IS_ENABLED(CONFIG_SUSPEND))
249 return;
250
251 ret = psci_features(PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND));
252
253 if (ret != PSCI_RET_NOT_SUPPORTED)
254 suspend_set_ops(&psci_suspend_ops);
255}
256
257static void __init psci_init_cpu_suspend(void)
258{
259 int feature = psci_features(psci_function_id[PSCI_FN_CPU_SUSPEND]);
260
261 if (feature != PSCI_RET_NOT_SUPPORTED)
262 psci_cpu_suspend_feature = feature;
263}
264
184/* 265/*
185 * Detect the presence of a resident Trusted OS which may cause CPU_OFF to 266 * Detect the presence of a resident Trusted OS which may cause CPU_OFF to
186 * return DENIED (which would be fatal). 267 * return DENIED (which would be fatal).
@@ -224,16 +305,17 @@ static void __init psci_init_migrate(void)
224static void __init psci_0_2_set_functions(void) 305static void __init psci_0_2_set_functions(void)
225{ 306{
226 pr_info("Using standard PSCI v0.2 function IDs\n"); 307 pr_info("Using standard PSCI v0.2 function IDs\n");
227 psci_function_id[PSCI_FN_CPU_SUSPEND] = PSCI_0_2_FN_NATIVE(CPU_SUSPEND); 308 psci_function_id[PSCI_FN_CPU_SUSPEND] =
309 PSCI_FN_NATIVE(0_2, CPU_SUSPEND);
228 psci_ops.cpu_suspend = psci_cpu_suspend; 310 psci_ops.cpu_suspend = psci_cpu_suspend;
229 311
230 psci_function_id[PSCI_FN_CPU_OFF] = PSCI_0_2_FN_CPU_OFF; 312 psci_function_id[PSCI_FN_CPU_OFF] = PSCI_0_2_FN_CPU_OFF;
231 psci_ops.cpu_off = psci_cpu_off; 313 psci_ops.cpu_off = psci_cpu_off;
232 314
233 psci_function_id[PSCI_FN_CPU_ON] = PSCI_0_2_FN_NATIVE(CPU_ON); 315 psci_function_id[PSCI_FN_CPU_ON] = PSCI_FN_NATIVE(0_2, CPU_ON);
234 psci_ops.cpu_on = psci_cpu_on; 316 psci_ops.cpu_on = psci_cpu_on;
235 317
236 psci_function_id[PSCI_FN_MIGRATE] = PSCI_0_2_FN_NATIVE(MIGRATE); 318 psci_function_id[PSCI_FN_MIGRATE] = PSCI_FN_NATIVE(0_2, MIGRATE);
237 psci_ops.migrate = psci_migrate; 319 psci_ops.migrate = psci_migrate;
238 320
239 psci_ops.affinity_info = psci_affinity_info; 321 psci_ops.affinity_info = psci_affinity_info;
@@ -265,6 +347,11 @@ static int __init psci_probe(void)
265 347
266 psci_init_migrate(); 348 psci_init_migrate();
267 349
350 if (PSCI_VERSION_MAJOR(ver) >= 1) {
351 psci_init_cpu_suspend();
352 psci_init_system_suspend();
353 }
354
268 return 0; 355 return 0;
269} 356}
270 357
@@ -340,6 +427,7 @@ out_put_node:
340static const struct of_device_id const psci_of_match[] __initconst = { 427static const struct of_device_id const psci_of_match[] __initconst = {
341 { .compatible = "arm,psci", .data = psci_0_1_init}, 428 { .compatible = "arm,psci", .data = psci_0_1_init},
342 { .compatible = "arm,psci-0.2", .data = psci_0_2_init}, 429 { .compatible = "arm,psci-0.2", .data = psci_0_2_init},
430 { .compatible = "arm,psci-1.0", .data = psci_0_2_init},
343 {}, 431 {},
344}; 432};
345 433
diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c
index 29e6850665eb..0883292f640f 100644
--- a/drivers/firmware/qcom_scm-32.c
+++ b/drivers/firmware/qcom_scm-32.c
@@ -480,15 +480,15 @@ void __qcom_scm_cpu_power_down(u32 flags)
480int __qcom_scm_is_call_available(u32 svc_id, u32 cmd_id) 480int __qcom_scm_is_call_available(u32 svc_id, u32 cmd_id)
481{ 481{
482 int ret; 482 int ret;
483 u32 svc_cmd = (svc_id << 10) | cmd_id; 483 __le32 svc_cmd = cpu_to_le32((svc_id << 10) | cmd_id);
484 u32 ret_val = 0; 484 __le32 ret_val = 0;
485 485
486 ret = qcom_scm_call(QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD, &svc_cmd, 486 ret = qcom_scm_call(QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD, &svc_cmd,
487 sizeof(svc_cmd), &ret_val, sizeof(ret_val)); 487 sizeof(svc_cmd), &ret_val, sizeof(ret_val));
488 if (ret) 488 if (ret)
489 return ret; 489 return ret;
490 490
491 return ret_val; 491 return le32_to_cpu(ret_val);
492} 492}
493 493
494int __qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp) 494int __qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp)
diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
new file mode 100644
index 000000000000..dd506cd3a5b8
--- /dev/null
+++ b/drivers/firmware/raspberrypi.c
@@ -0,0 +1,260 @@
1/*
2 * Defines interfaces for interacting wtih the Raspberry Pi firmware's
3 * property channel.
4 *
5 * Copyright © 2015 Broadcom
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/dma-mapping.h>
13#include <linux/mailbox_client.h>
14#include <linux/module.h>
15#include <linux/of_platform.h>
16#include <linux/platform_device.h>
17#include <soc/bcm2835/raspberrypi-firmware.h>
18
19#define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf))
20#define MBOX_CHAN(msg) ((msg) & 0xf)
21#define MBOX_DATA28(msg) ((msg) & ~0xf)
22#define MBOX_CHAN_PROPERTY 8
23
24struct rpi_firmware {
25 struct mbox_client cl;
26 struct mbox_chan *chan; /* The property channel. */
27 struct completion c;
28 u32 enabled;
29};
30
31static DEFINE_MUTEX(transaction_lock);
32
33static void response_callback(struct mbox_client *cl, void *msg)
34{
35 struct rpi_firmware *fw = container_of(cl, struct rpi_firmware, cl);
36 complete(&fw->c);
37}
38
39/*
40 * Sends a request to the firmware through the BCM2835 mailbox driver,
41 * and synchronously waits for the reply.
42 */
43static int
44rpi_firmware_transaction(struct rpi_firmware *fw, u32 chan, u32 data)
45{
46 u32 message = MBOX_MSG(chan, data);
47 int ret;
48
49 WARN_ON(data & 0xf);
50
51 mutex_lock(&transaction_lock);
52 reinit_completion(&fw->c);
53 ret = mbox_send_message(fw->chan, &message);
54 if (ret >= 0) {
55 wait_for_completion(&fw->c);
56 ret = 0;
57 } else {
58 dev_err(fw->cl.dev, "mbox_send_message returned %d\n", ret);
59 }
60 mutex_unlock(&transaction_lock);
61
62 return ret;
63}
64
65/**
66 * rpi_firmware_property_list - Submit firmware property list
67 * @fw: Pointer to firmware structure from rpi_firmware_get().
68 * @data: Buffer holding tags.
69 * @tag_size: Size of tags buffer.
70 *
71 * Submits a set of concatenated tags to the VPU firmware through the
72 * mailbox property interface.
73 *
74 * The buffer header and the ending tag are added by this function and
75 * don't need to be supplied, just the actual tags for your operation.
76 * See struct rpi_firmware_property_tag_header for the per-tag
77 * structure.
78 */
79int rpi_firmware_property_list(struct rpi_firmware *fw,
80 void *data, size_t tag_size)
81{
82 size_t size = tag_size + 12;
83 u32 *buf;
84 dma_addr_t bus_addr;
85 int ret;
86
87 /* Packets are processed a dword at a time. */
88 if (size & 3)
89 return -EINVAL;
90
91 buf = dma_alloc_coherent(fw->cl.dev, PAGE_ALIGN(size), &bus_addr,
92 GFP_ATOMIC);
93 if (!buf)
94 return -ENOMEM;
95
96 /* The firmware will error out without parsing in this case. */
97 WARN_ON(size >= 1024 * 1024);
98
99 buf[0] = size;
100 buf[1] = RPI_FIRMWARE_STATUS_REQUEST;
101 memcpy(&buf[2], data, tag_size);
102 buf[size / 4 - 1] = RPI_FIRMWARE_PROPERTY_END;
103 wmb();
104
105 ret = rpi_firmware_transaction(fw, MBOX_CHAN_PROPERTY, bus_addr);
106
107 rmb();
108 memcpy(data, &buf[2], tag_size);
109 if (ret == 0 && buf[1] != RPI_FIRMWARE_STATUS_SUCCESS) {
110 /*
111 * The tag name here might not be the one causing the
112 * error, if there were multiple tags in the request.
113 * But single-tag is the most common, so go with it.
114 */
115 dev_err(fw->cl.dev, "Request 0x%08x returned status 0x%08x\n",
116 buf[2], buf[1]);
117 ret = -EINVAL;
118 }
119
120 dma_free_coherent(fw->cl.dev, PAGE_ALIGN(size), buf, bus_addr);
121
122 return ret;
123}
124EXPORT_SYMBOL_GPL(rpi_firmware_property_list);
125
126/**
127 * rpi_firmware_property - Submit single firmware property
128 * @fw: Pointer to firmware structure from rpi_firmware_get().
129 * @tag: One of enum_mbox_property_tag.
130 * @tag_data: Tag data buffer.
131 * @buf_size: Buffer size.
132 *
133 * Submits a single tag to the VPU firmware through the mailbox
134 * property interface.
135 *
136 * This is a convenience wrapper around
137 * rpi_firmware_property_list() to avoid some of the
138 * boilerplate in property calls.
139 */
140int rpi_firmware_property(struct rpi_firmware *fw,
141 u32 tag, void *tag_data, size_t buf_size)
142{
143 /* Single tags are very small (generally 8 bytes), so the
144 * stack should be safe.
145 */
146 u8 data[buf_size + sizeof(struct rpi_firmware_property_tag_header)];
147 struct rpi_firmware_property_tag_header *header =
148 (struct rpi_firmware_property_tag_header *)data;
149 int ret;
150
151 header->tag = tag;
152 header->buf_size = buf_size;
153 header->req_resp_size = 0;
154 memcpy(data + sizeof(struct rpi_firmware_property_tag_header),
155 tag_data, buf_size);
156
157 ret = rpi_firmware_property_list(fw, &data, sizeof(data));
158 memcpy(tag_data,
159 data + sizeof(struct rpi_firmware_property_tag_header),
160 buf_size);
161
162 return ret;
163}
164EXPORT_SYMBOL_GPL(rpi_firmware_property);
165
166static void
167rpi_firmware_print_firmware_revision(struct rpi_firmware *fw)
168{
169 u32 packet;
170 int ret = rpi_firmware_property(fw,
171 RPI_FIRMWARE_GET_FIRMWARE_REVISION,
172 &packet, sizeof(packet));
173
174 if (ret == 0) {
175 struct tm tm;
176
177 time_to_tm(packet, 0, &tm);
178
179 dev_info(fw->cl.dev,
180 "Attached to firmware from %04ld-%02d-%02d %02d:%02d\n",
181 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
182 tm.tm_hour, tm.tm_min);
183 }
184}
185
186static int rpi_firmware_probe(struct platform_device *pdev)
187{
188 struct device *dev = &pdev->dev;
189 struct rpi_firmware *fw;
190
191 fw = devm_kzalloc(dev, sizeof(*fw), GFP_KERNEL);
192 if (!fw)
193 return -ENOMEM;
194
195 fw->cl.dev = dev;
196 fw->cl.rx_callback = response_callback;
197 fw->cl.tx_block = true;
198
199 fw->chan = mbox_request_channel(&fw->cl, 0);
200 if (IS_ERR(fw->chan)) {
201 int ret = PTR_ERR(fw->chan);
202 if (ret != -EPROBE_DEFER)
203 dev_err(dev, "Failed to get mbox channel: %d\n", ret);
204 return ret;
205 }
206
207 init_completion(&fw->c);
208
209 platform_set_drvdata(pdev, fw);
210
211 rpi_firmware_print_firmware_revision(fw);
212
213 return 0;
214}
215
216static int rpi_firmware_remove(struct platform_device *pdev)
217{
218 struct rpi_firmware *fw = platform_get_drvdata(pdev);
219
220 mbox_free_channel(fw->chan);
221
222 return 0;
223}
224
225/**
226 * rpi_firmware_get - Get pointer to rpi_firmware structure.
227 * @firmware_node: Pointer to the firmware Device Tree node.
228 *
229 * Returns NULL is the firmware device is not ready.
230 */
231struct rpi_firmware *rpi_firmware_get(struct device_node *firmware_node)
232{
233 struct platform_device *pdev = of_find_device_by_node(firmware_node);
234
235 if (!pdev)
236 return NULL;
237
238 return platform_get_drvdata(pdev);
239}
240EXPORT_SYMBOL_GPL(rpi_firmware_get);
241
242static const struct of_device_id rpi_firmware_of_match[] = {
243 { .compatible = "raspberrypi,bcm2835-firmware", },
244 {},
245};
246MODULE_DEVICE_TABLE(of, rpi_firmware_of_match);
247
248static struct platform_driver rpi_firmware_driver = {
249 .driver = {
250 .name = "raspberrypi-firmware",
251 .of_match_table = rpi_firmware_of_match,
252 },
253 .probe = rpi_firmware_probe,
254 .remove = rpi_firmware_remove,
255};
256module_platform_driver(rpi_firmware_driver);
257
258MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
259MODULE_DESCRIPTION("Raspberry Pi firmware driver");
260MODULE_LICENSE("GPL v2");
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 796569eeaf1d..842b0043ad94 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -321,6 +321,14 @@ config SENSORS_APPLESMC
321 Say Y here if you have an applicable laptop and want to experience 321 Say Y here if you have an applicable laptop and want to experience
322 the awesome power of applesmc. 322 the awesome power of applesmc.
323 323
324config SENSORS_ARM_SCPI
325 tristate "ARM SCPI Sensors"
326 depends on ARM_SCPI_PROTOCOL
327 help
328 This driver provides support for temperature, voltage, current
329 and power sensors available on ARM Ltd's SCP based platforms. The
330 actual number and type of sensors exported depend on the platform.
331
324config SENSORS_ASB100 332config SENSORS_ASB100
325 tristate "Asus ASB100 Bach" 333 tristate "Asus ASB100 Bach"
326 depends on X86 && I2C 334 depends on X86 && I2C
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 01855ee641d1..12a32398fdcc 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -44,6 +44,7 @@ obj-$(CONFIG_SENSORS_ADT7462) += adt7462.o
44obj-$(CONFIG_SENSORS_ADT7470) += adt7470.o 44obj-$(CONFIG_SENSORS_ADT7470) += adt7470.o
45obj-$(CONFIG_SENSORS_ADT7475) += adt7475.o 45obj-$(CONFIG_SENSORS_ADT7475) += adt7475.o
46obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o 46obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o
47obj-$(CONFIG_SENSORS_ARM_SCPI) += scpi-hwmon.o
47obj-$(CONFIG_SENSORS_ASC7621) += asc7621.o 48obj-$(CONFIG_SENSORS_ASC7621) += asc7621.o
48obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o 49obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
49obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o 50obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o
diff --git a/drivers/hwmon/scpi-hwmon.c b/drivers/hwmon/scpi-hwmon.c
new file mode 100644
index 000000000000..2c1241bbf9af
--- /dev/null
+++ b/drivers/hwmon/scpi-hwmon.c
@@ -0,0 +1,288 @@
1/*
2 * System Control and Power Interface(SCPI) based hwmon sensor driver
3 *
4 * Copyright (C) 2015 ARM Ltd.
5 * Punit Agrawal <punit.agrawal@arm.com>
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 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
12 * kind, whether express or implied; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/hwmon.h>
18#include <linux/module.h>
19#include <linux/platform_device.h>
20#include <linux/scpi_protocol.h>
21#include <linux/slab.h>
22#include <linux/sysfs.h>
23#include <linux/thermal.h>
24
25struct sensor_data {
26 struct scpi_sensor_info info;
27 struct device_attribute dev_attr_input;
28 struct device_attribute dev_attr_label;
29 char input[20];
30 char label[20];
31};
32
33struct scpi_thermal_zone {
34 struct list_head list;
35 int sensor_id;
36 struct scpi_sensors *scpi_sensors;
37 struct thermal_zone_device *tzd;
38};
39
40struct scpi_sensors {
41 struct scpi_ops *scpi_ops;
42 struct sensor_data *data;
43 struct list_head thermal_zones;
44 struct attribute **attrs;
45 struct attribute_group group;
46 const struct attribute_group *groups[2];
47};
48
49static int scpi_read_temp(void *dev, int *temp)
50{
51 struct scpi_thermal_zone *zone = dev;
52 struct scpi_sensors *scpi_sensors = zone->scpi_sensors;
53 struct scpi_ops *scpi_ops = scpi_sensors->scpi_ops;
54 struct sensor_data *sensor = &scpi_sensors->data[zone->sensor_id];
55 u32 value;
56 int ret;
57
58 ret = scpi_ops->sensor_get_value(sensor->info.sensor_id, &value);
59 if (ret)
60 return ret;
61
62 *temp = value;
63 return 0;
64}
65
66/* hwmon callback functions */
67static ssize_t
68scpi_show_sensor(struct device *dev, struct device_attribute *attr, char *buf)
69{
70 struct scpi_sensors *scpi_sensors = dev_get_drvdata(dev);
71 struct scpi_ops *scpi_ops = scpi_sensors->scpi_ops;
72 struct sensor_data *sensor;
73 u32 value;
74 int ret;
75
76 sensor = container_of(attr, struct sensor_data, dev_attr_input);
77
78 ret = scpi_ops->sensor_get_value(sensor->info.sensor_id, &value);
79 if (ret)
80 return ret;
81
82 return sprintf(buf, "%u\n", value);
83}
84
85static ssize_t
86scpi_show_label(struct device *dev, struct device_attribute *attr, char *buf)
87{
88 struct sensor_data *sensor;
89
90 sensor = container_of(attr, struct sensor_data, dev_attr_label);
91
92 return sprintf(buf, "%s\n", sensor->info.name);
93}
94
95static void
96unregister_thermal_zones(struct platform_device *pdev,
97 struct scpi_sensors *scpi_sensors)
98{
99 struct list_head *pos;
100
101 list_for_each(pos, &scpi_sensors->thermal_zones) {
102 struct scpi_thermal_zone *zone;
103
104 zone = list_entry(pos, struct scpi_thermal_zone, list);
105 thermal_zone_of_sensor_unregister(&pdev->dev, zone->tzd);
106 }
107}
108
109static struct thermal_zone_of_device_ops scpi_sensor_ops = {
110 .get_temp = scpi_read_temp,
111};
112
113static int scpi_hwmon_probe(struct platform_device *pdev)
114{
115 u16 nr_sensors, i;
116 int num_temp = 0, num_volt = 0, num_current = 0, num_power = 0;
117 struct scpi_ops *scpi_ops;
118 struct device *hwdev, *dev = &pdev->dev;
119 struct scpi_sensors *scpi_sensors;
120 int ret;
121
122 scpi_ops = get_scpi_ops();
123 if (!scpi_ops)
124 return -EPROBE_DEFER;
125
126 ret = scpi_ops->sensor_get_capability(&nr_sensors);
127 if (ret)
128 return ret;
129
130 if (!nr_sensors)
131 return -ENODEV;
132
133 scpi_sensors = devm_kzalloc(dev, sizeof(*scpi_sensors), GFP_KERNEL);
134 if (!scpi_sensors)
135 return -ENOMEM;
136
137 scpi_sensors->data = devm_kcalloc(dev, nr_sensors,
138 sizeof(*scpi_sensors->data), GFP_KERNEL);
139 if (!scpi_sensors->data)
140 return -ENOMEM;
141
142 scpi_sensors->attrs = devm_kcalloc(dev, (nr_sensors * 2) + 1,
143 sizeof(*scpi_sensors->attrs), GFP_KERNEL);
144 if (!scpi_sensors->attrs)
145 return -ENOMEM;
146
147 scpi_sensors->scpi_ops = scpi_ops;
148
149 for (i = 0; i < nr_sensors; i++) {
150 struct sensor_data *sensor = &scpi_sensors->data[i];
151
152 ret = scpi_ops->sensor_get_info(i, &sensor->info);
153 if (ret)
154 return ret;
155
156 switch (sensor->info.class) {
157 case TEMPERATURE:
158 snprintf(sensor->input, sizeof(sensor->input),
159 "temp%d_input", num_temp + 1);
160 snprintf(sensor->label, sizeof(sensor->input),
161 "temp%d_label", num_temp + 1);
162 num_temp++;
163 break;
164 case VOLTAGE:
165 snprintf(sensor->input, sizeof(sensor->input),
166 "in%d_input", num_volt);
167 snprintf(sensor->label, sizeof(sensor->input),
168 "in%d_label", num_volt);
169 num_volt++;
170 break;
171 case CURRENT:
172 snprintf(sensor->input, sizeof(sensor->input),
173 "curr%d_input", num_current + 1);
174 snprintf(sensor->label, sizeof(sensor->input),
175 "curr%d_label", num_current + 1);
176 num_current++;
177 break;
178 case POWER:
179 snprintf(sensor->input, sizeof(sensor->input),
180 "power%d_input", num_power + 1);
181 snprintf(sensor->label, sizeof(sensor->input),
182 "power%d_label", num_power + 1);
183 num_power++;
184 break;
185 default:
186 break;
187 }
188
189 sensor->dev_attr_input.attr.mode = S_IRUGO;
190 sensor->dev_attr_input.show = scpi_show_sensor;
191 sensor->dev_attr_input.attr.name = sensor->input;
192
193 sensor->dev_attr_label.attr.mode = S_IRUGO;
194 sensor->dev_attr_label.show = scpi_show_label;
195 sensor->dev_attr_label.attr.name = sensor->label;
196
197 scpi_sensors->attrs[i << 1] = &sensor->dev_attr_input.attr;
198 scpi_sensors->attrs[(i << 1) + 1] = &sensor->dev_attr_label.attr;
199
200 sysfs_attr_init(scpi_sensors->attrs[i << 1]);
201 sysfs_attr_init(scpi_sensors->attrs[(i << 1) + 1]);
202 }
203
204 scpi_sensors->group.attrs = scpi_sensors->attrs;
205 scpi_sensors->groups[0] = &scpi_sensors->group;
206
207 platform_set_drvdata(pdev, scpi_sensors);
208
209 hwdev = devm_hwmon_device_register_with_groups(dev,
210 "scpi_sensors", scpi_sensors, scpi_sensors->groups);
211
212 if (IS_ERR(hwdev))
213 return PTR_ERR(hwdev);
214
215 /*
216 * Register the temperature sensors with the thermal framework
217 * to allow their usage in setting up the thermal zones from
218 * device tree.
219 *
220 * NOTE: Not all temperature sensors maybe used for thermal
221 * control
222 */
223 INIT_LIST_HEAD(&scpi_sensors->thermal_zones);
224 for (i = 0; i < nr_sensors; i++) {
225 struct sensor_data *sensor = &scpi_sensors->data[i];
226 struct scpi_thermal_zone *zone;
227
228 if (sensor->info.class != TEMPERATURE)
229 continue;
230
231 zone = devm_kzalloc(dev, sizeof(*zone), GFP_KERNEL);
232 if (!zone) {
233 ret = -ENOMEM;
234 goto unregister_tzd;
235 }
236
237 zone->sensor_id = i;
238 zone->scpi_sensors = scpi_sensors;
239 zone->tzd = thermal_zone_of_sensor_register(dev, i, zone,
240 &scpi_sensor_ops);
241 /*
242 * The call to thermal_zone_of_sensor_register returns
243 * an error for sensors that are not associated with
244 * any thermal zones or if the thermal subsystem is
245 * not configured.
246 */
247 if (IS_ERR(zone->tzd)) {
248 devm_kfree(dev, zone);
249 continue;
250 }
251 list_add(&zone->list, &scpi_sensors->thermal_zones);
252 }
253
254 return 0;
255
256unregister_tzd:
257 unregister_thermal_zones(pdev, scpi_sensors);
258 return ret;
259}
260
261static int scpi_hwmon_remove(struct platform_device *pdev)
262{
263 struct scpi_sensors *scpi_sensors = platform_get_drvdata(pdev);
264
265 unregister_thermal_zones(pdev, scpi_sensors);
266
267 return 0;
268}
269
270static const struct of_device_id scpi_of_match[] = {
271 {.compatible = "arm,scpi-sensors"},
272 {},
273};
274
275static struct platform_driver scpi_hwmon_platdrv = {
276 .driver = {
277 .name = "scpi-hwmon",
278 .owner = THIS_MODULE,
279 .of_match_table = scpi_of_match,
280 },
281 .probe = scpi_hwmon_probe,
282 .remove = scpi_hwmon_remove,
283};
284module_platform_driver(scpi_hwmon_platdrv);
285
286MODULE_AUTHOR("Punit Agrawal <punit.agrawal@arm.com>");
287MODULE_DESCRIPTION("ARM SCPI HWMON interface driver");
288MODULE_LICENSE("GPL v2");
diff --git a/drivers/memory/pl172.c b/drivers/memory/pl172.c
index b2ef6072fbf4..ff57195b4e37 100644
--- a/drivers/memory/pl172.c
+++ b/drivers/memory/pl172.c
@@ -118,7 +118,8 @@ static int pl172_setup_static(struct amba_device *adev,
118 if (of_property_read_bool(np, "mpmc,extended-wait")) 118 if (of_property_read_bool(np, "mpmc,extended-wait"))
119 cfg |= MPMC_STATIC_CFG_EW; 119 cfg |= MPMC_STATIC_CFG_EW;
120 120
121 if (of_property_read_bool(np, "mpmc,buffer-enable")) 121 if (amba_part(adev) == 0x172 &&
122 of_property_read_bool(np, "mpmc,buffer-enable"))
122 cfg |= MPMC_STATIC_CFG_B; 123 cfg |= MPMC_STATIC_CFG_B;
123 124
124 if (of_property_read_bool(np, "mpmc,write-protect")) 125 if (of_property_read_bool(np, "mpmc,write-protect"))
@@ -190,6 +191,8 @@ static int pl172_parse_cs_config(struct amba_device *adev,
190} 191}
191 192
192static const char * const pl172_revisions[] = {"r1", "r2", "r2p3", "r2p4"}; 193static const char * const pl172_revisions[] = {"r1", "r2", "r2p3", "r2p4"};
194static const char * const pl175_revisions[] = {"r1"};
195static const char * const pl176_revisions[] = {"r0"};
193 196
194static int pl172_probe(struct amba_device *adev, const struct amba_id *id) 197static int pl172_probe(struct amba_device *adev, const struct amba_id *id)
195{ 198{
@@ -202,6 +205,12 @@ static int pl172_probe(struct amba_device *adev, const struct amba_id *id)
202 if (amba_part(adev) == 0x172) { 205 if (amba_part(adev) == 0x172) {
203 if (amba_rev(adev) < ARRAY_SIZE(pl172_revisions)) 206 if (amba_rev(adev) < ARRAY_SIZE(pl172_revisions))
204 rev = pl172_revisions[amba_rev(adev)]; 207 rev = pl172_revisions[amba_rev(adev)];
208 } else if (amba_part(adev) == 0x175) {
209 if (amba_rev(adev) < ARRAY_SIZE(pl175_revisions))
210 rev = pl175_revisions[amba_rev(adev)];
211 } else if (amba_part(adev) == 0x176) {
212 if (amba_rev(adev) < ARRAY_SIZE(pl176_revisions))
213 rev = pl176_revisions[amba_rev(adev)];
205 } 214 }
206 215
207 dev_info(dev, "ARM PL%x revision %s\n", amba_part(adev), rev); 216 dev_info(dev, "ARM PL%x revision %s\n", amba_part(adev), rev);
@@ -278,9 +287,20 @@ static int pl172_remove(struct amba_device *adev)
278} 287}
279 288
280static const struct amba_id pl172_ids[] = { 289static const struct amba_id pl172_ids[] = {
290 /* PrimeCell MPMC PL172, EMC found on NXP LPC18xx and LPC43xx */
281 { 291 {
282 .id = 0x07341172, 292 .id = 0x07041172,
283 .mask = 0xffffffff, 293 .mask = 0x3f0fffff,
294 },
295 /* PrimeCell MPMC PL175, EMC found on NXP LPC32xx */
296 {
297 .id = 0x07041175,
298 .mask = 0x3f0fffff,
299 },
300 /* PrimeCell MPMC PL176 */
301 {
302 .id = 0x89041176,
303 .mask = 0xff0fffff,
284 }, 304 },
285 { 0, 0 }, 305 { 0, 0 },
286}; 306};
diff --git a/drivers/misc/atmel_tclib.c b/drivers/misc/atmel_tclib.c
index 0ca05c3ec8d6..ac24a4bd63f7 100644
--- a/drivers/misc/atmel_tclib.c
+++ b/drivers/misc/atmel_tclib.c
@@ -125,6 +125,10 @@ static int __init tc_probe(struct platform_device *pdev)
125 if (IS_ERR(clk)) 125 if (IS_ERR(clk))
126 return PTR_ERR(clk); 126 return PTR_ERR(clk);
127 127
128 tc->slow_clk = devm_clk_get(&pdev->dev, "slow_clk");
129 if (IS_ERR(tc->slow_clk))
130 return PTR_ERR(tc->slow_clk);
131
128 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 132 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
129 tc->regs = devm_ioremap_resource(&pdev->dev, r); 133 tc->regs = devm_ioremap_resource(&pdev->dev, r);
130 if (IS_ERR(tc->regs)) 134 if (IS_ERR(tc->regs))
diff --git a/drivers/pwm/pwm-atmel-tcb.c b/drivers/pwm/pwm-atmel-tcb.c
index 6da01b3bf6f4..75db585a2a94 100644
--- a/drivers/pwm/pwm-atmel-tcb.c
+++ b/drivers/pwm/pwm-atmel-tcb.c
@@ -305,7 +305,7 @@ static int atmel_tcb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
305 */ 305 */
306 if (i == 5) { 306 if (i == 5) {
307 i = slowclk; 307 i = slowclk;
308 rate = 32768; 308 rate = clk_get_rate(tc->slow_clk);
309 min = div_u64(NSEC_PER_SEC, rate); 309 min = div_u64(NSEC_PER_SEC, rate);
310 max = min << tc->tcb_config->counter_width; 310 max = min << tc->tcb_config->counter_width;
311 311
@@ -387,9 +387,9 @@ static int atmel_tcb_pwm_probe(struct platform_device *pdev)
387 387
388 tcbpwm = devm_kzalloc(&pdev->dev, sizeof(*tcbpwm), GFP_KERNEL); 388 tcbpwm = devm_kzalloc(&pdev->dev, sizeof(*tcbpwm), GFP_KERNEL);
389 if (tcbpwm == NULL) { 389 if (tcbpwm == NULL) {
390 atmel_tc_free(tc); 390 err = -ENOMEM;
391 dev_err(&pdev->dev, "failed to allocate memory\n"); 391 dev_err(&pdev->dev, "failed to allocate memory\n");
392 return -ENOMEM; 392 goto err_free_tc;
393 } 393 }
394 394
395 tcbpwm->chip.dev = &pdev->dev; 395 tcbpwm->chip.dev = &pdev->dev;
@@ -400,17 +400,27 @@ static int atmel_tcb_pwm_probe(struct platform_device *pdev)
400 tcbpwm->chip.npwm = NPWM; 400 tcbpwm->chip.npwm = NPWM;
401 tcbpwm->tc = tc; 401 tcbpwm->tc = tc;
402 402
403 err = clk_prepare_enable(tc->slow_clk);
404 if (err)
405 goto err_free_tc;
406
403 spin_lock_init(&tcbpwm->lock); 407 spin_lock_init(&tcbpwm->lock);
404 408
405 err = pwmchip_add(&tcbpwm->chip); 409 err = pwmchip_add(&tcbpwm->chip);
406 if (err < 0) { 410 if (err < 0)
407 atmel_tc_free(tc); 411 goto err_disable_clk;
408 return err;
409 }
410 412
411 platform_set_drvdata(pdev, tcbpwm); 413 platform_set_drvdata(pdev, tcbpwm);
412 414
413 return 0; 415 return 0;
416
417err_disable_clk:
418 clk_disable_unprepare(tcbpwm->tc->slow_clk);
419
420err_free_tc:
421 atmel_tc_free(tc);
422
423 return err;
414} 424}
415 425
416static int atmel_tcb_pwm_remove(struct platform_device *pdev) 426static int atmel_tcb_pwm_remove(struct platform_device *pdev)
@@ -418,6 +428,8 @@ static int atmel_tcb_pwm_remove(struct platform_device *pdev)
418 struct atmel_tcb_pwm_chip *tcbpwm = platform_get_drvdata(pdev); 428 struct atmel_tcb_pwm_chip *tcbpwm = platform_get_drvdata(pdev);
419 int err; 429 int err;
420 430
431 clk_disable_unprepare(tcbpwm->tc->slow_clk);
432
421 err = pwmchip_remove(&tcbpwm->chip); 433 err = pwmchip_remove(&tcbpwm->chip);
422 if (err < 0) 434 if (err < 0)
423 return err; 435 return err;
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index c9c0fcce98a7..4e853ed2c82b 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -3,6 +3,7 @@ menu "SOC (System On Chip) specific Drivers"
3source "drivers/soc/brcmstb/Kconfig" 3source "drivers/soc/brcmstb/Kconfig"
4source "drivers/soc/mediatek/Kconfig" 4source "drivers/soc/mediatek/Kconfig"
5source "drivers/soc/qcom/Kconfig" 5source "drivers/soc/qcom/Kconfig"
6source "drivers/soc/rockchip/Kconfig"
6source "drivers/soc/sunxi/Kconfig" 7source "drivers/soc/sunxi/Kconfig"
7source "drivers/soc/ti/Kconfig" 8source "drivers/soc/ti/Kconfig"
8source "drivers/soc/versatile/Kconfig" 9source "drivers/soc/versatile/Kconfig"
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 4e27f10367f0..f2ba2e932ae1 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_SOC_BRCMSTB) += brcmstb/
6obj-$(CONFIG_MACH_DOVE) += dove/ 6obj-$(CONFIG_MACH_DOVE) += dove/
7obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ 7obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
8obj-$(CONFIG_ARCH_QCOM) += qcom/ 8obj-$(CONFIG_ARCH_QCOM) += qcom/
9obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
9obj-$(CONFIG_ARCH_SUNXI) += sunxi/ 10obj-$(CONFIG_ARCH_SUNXI) += sunxi/
10obj-$(CONFIG_ARCH_TEGRA) += tegra/ 11obj-$(CONFIG_ARCH_TEGRA) += tegra/
11obj-$(CONFIG_SOC_TI) += ti/ 12obj-$(CONFIG_SOC_TI) += ti/
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index ba47b70f4d85..eec76141d9b9 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -19,6 +19,15 @@ config QCOM_PM
19 modes. It interface with various system drivers to put the cores in 19 modes. It interface with various system drivers to put the cores in
20 low power modes. 20 low power modes.
21 21
22config QCOM_SMEM
23 tristate "Qualcomm Shared Memory Manager (SMEM)"
24 depends on ARCH_QCOM
25 depends on HWSPINLOCK
26 help
27 Say y here to enable support for the Qualcomm Shared Memory Manager.
28 The driver provides an interface to items in a heap shared among all
29 processors in a Qualcomm platform.
30
22config QCOM_SMD 31config QCOM_SMD
23 tristate "Qualcomm Shared Memory Driver (SMD)" 32 tristate "Qualcomm Shared Memory Driver (SMD)"
24 depends on QCOM_SMEM 33 depends on QCOM_SMEM
@@ -40,11 +49,3 @@ config QCOM_SMD_RPM
40 49
41 Say M here if you want to include support for the Qualcomm RPM as a 50 Say M here if you want to include support for the Qualcomm RPM as a
42 module. This will build a module called "qcom-smd-rpm". 51 module. This will build a module called "qcom-smd-rpm".
43
44config QCOM_SMEM
45 tristate "Qualcomm Shared Memory Manager (SMEM)"
46 depends on ARCH_QCOM
47 help
48 Say y here to enable support for the Qualcomm Shared Memory Manager.
49 The driver provides an interface to items in a heap shared among all
50 processors in a Qualcomm platform.
diff --git a/drivers/soc/qcom/smd-rpm.c b/drivers/soc/qcom/smd-rpm.c
index 1392ccf14a20..2969321e1b09 100644
--- a/drivers/soc/qcom/smd-rpm.c
+++ b/drivers/soc/qcom/smd-rpm.c
@@ -17,6 +17,7 @@
17#include <linux/of_platform.h> 17#include <linux/of_platform.h>
18#include <linux/io.h> 18#include <linux/io.h>
19#include <linux/interrupt.h> 19#include <linux/interrupt.h>
20#include <linux/slab.h>
20 21
21#include <linux/soc/qcom/smd.h> 22#include <linux/soc/qcom/smd.h>
22#include <linux/soc/qcom/smd-rpm.h> 23#include <linux/soc/qcom/smd-rpm.h>
@@ -44,8 +45,8 @@ struct qcom_smd_rpm {
44 * @length: length of the payload 45 * @length: length of the payload
45 */ 46 */
46struct qcom_rpm_header { 47struct qcom_rpm_header {
47 u32 service_type; 48 __le32 service_type;
48 u32 length; 49 __le32 length;
49}; 50};
50 51
51/** 52/**
@@ -57,11 +58,11 @@ struct qcom_rpm_header {
57 * @data_len: length of the payload following this header 58 * @data_len: length of the payload following this header
58 */ 59 */
59struct qcom_rpm_request { 60struct qcom_rpm_request {
60 u32 msg_id; 61 __le32 msg_id;
61 u32 flags; 62 __le32 flags;
62 u32 type; 63 __le32 type;
63 u32 id; 64 __le32 id;
64 u32 data_len; 65 __le32 data_len;
65}; 66};
66 67
67/** 68/**
@@ -74,10 +75,10 @@ struct qcom_rpm_request {
74 * Multiple of these messages can be stacked in an rpm message. 75 * Multiple of these messages can be stacked in an rpm message.
75 */ 76 */
76struct qcom_rpm_message { 77struct qcom_rpm_message {
77 u32 msg_type; 78 __le32 msg_type;
78 u32 length; 79 __le32 length;
79 union { 80 union {
80 u32 msg_id; 81 __le32 msg_id;
81 u8 message[0]; 82 u8 message[0];
82 }; 83 };
83}; 84};
@@ -104,30 +105,34 @@ int qcom_rpm_smd_write(struct qcom_smd_rpm *rpm,
104 static unsigned msg_id = 1; 105 static unsigned msg_id = 1;
105 int left; 106 int left;
106 int ret; 107 int ret;
107
108 struct { 108 struct {
109 struct qcom_rpm_header hdr; 109 struct qcom_rpm_header hdr;
110 struct qcom_rpm_request req; 110 struct qcom_rpm_request req;
111 u8 payload[count]; 111 u8 payload[];
112 } pkt; 112 } *pkt;
113 size_t size = sizeof(*pkt) + count;
113 114
114 /* SMD packets to the RPM may not exceed 256 bytes */ 115 /* SMD packets to the RPM may not exceed 256 bytes */
115 if (WARN_ON(sizeof(pkt) >= 256)) 116 if (WARN_ON(size >= 256))
116 return -EINVAL; 117 return -EINVAL;
117 118
119 pkt = kmalloc(size, GFP_KERNEL);
120 if (!pkt)
121 return -ENOMEM;
122
118 mutex_lock(&rpm->lock); 123 mutex_lock(&rpm->lock);
119 124
120 pkt.hdr.service_type = RPM_SERVICE_TYPE_REQUEST; 125 pkt->hdr.service_type = cpu_to_le32(RPM_SERVICE_TYPE_REQUEST);
121 pkt.hdr.length = sizeof(struct qcom_rpm_request) + count; 126 pkt->hdr.length = cpu_to_le32(sizeof(struct qcom_rpm_request) + count);
122 127
123 pkt.req.msg_id = msg_id++; 128 pkt->req.msg_id = cpu_to_le32(msg_id++);
124 pkt.req.flags = BIT(state); 129 pkt->req.flags = cpu_to_le32(state);
125 pkt.req.type = type; 130 pkt->req.type = cpu_to_le32(type);
126 pkt.req.id = id; 131 pkt->req.id = cpu_to_le32(id);
127 pkt.req.data_len = count; 132 pkt->req.data_len = cpu_to_le32(count);
128 memcpy(pkt.payload, buf, count); 133 memcpy(pkt->payload, buf, count);
129 134
130 ret = qcom_smd_send(rpm->rpm_channel, &pkt, sizeof(pkt)); 135 ret = qcom_smd_send(rpm->rpm_channel, pkt, size);
131 if (ret) 136 if (ret)
132 goto out; 137 goto out;
133 138
@@ -138,6 +143,7 @@ int qcom_rpm_smd_write(struct qcom_smd_rpm *rpm,
138 ret = rpm->ack_status; 143 ret = rpm->ack_status;
139 144
140out: 145out:
146 kfree(pkt);
141 mutex_unlock(&rpm->lock); 147 mutex_unlock(&rpm->lock);
142 return ret; 148 return ret;
143} 149}
@@ -148,27 +154,29 @@ static int qcom_smd_rpm_callback(struct qcom_smd_device *qsdev,
148 size_t count) 154 size_t count)
149{ 155{
150 const struct qcom_rpm_header *hdr = data; 156 const struct qcom_rpm_header *hdr = data;
157 size_t hdr_length = le32_to_cpu(hdr->length);
151 const struct qcom_rpm_message *msg; 158 const struct qcom_rpm_message *msg;
152 struct qcom_smd_rpm *rpm = dev_get_drvdata(&qsdev->dev); 159 struct qcom_smd_rpm *rpm = dev_get_drvdata(&qsdev->dev);
153 const u8 *buf = data + sizeof(struct qcom_rpm_header); 160 const u8 *buf = data + sizeof(struct qcom_rpm_header);
154 const u8 *end = buf + hdr->length; 161 const u8 *end = buf + hdr_length;
155 char msgbuf[32]; 162 char msgbuf[32];
156 int status = 0; 163 int status = 0;
157 u32 len; 164 u32 len, msg_length;
158 165
159 if (hdr->service_type != RPM_SERVICE_TYPE_REQUEST || 166 if (le32_to_cpu(hdr->service_type) != RPM_SERVICE_TYPE_REQUEST ||
160 hdr->length < sizeof(struct qcom_rpm_message)) { 167 hdr_length < sizeof(struct qcom_rpm_message)) {
161 dev_err(&qsdev->dev, "invalid request\n"); 168 dev_err(&qsdev->dev, "invalid request\n");
162 return 0; 169 return 0;
163 } 170 }
164 171
165 while (buf < end) { 172 while (buf < end) {
166 msg = (struct qcom_rpm_message *)buf; 173 msg = (struct qcom_rpm_message *)buf;
167 switch (msg->msg_type) { 174 msg_length = le32_to_cpu(msg->length);
175 switch (le32_to_cpu(msg->msg_type)) {
168 case RPM_MSG_TYPE_MSG_ID: 176 case RPM_MSG_TYPE_MSG_ID:
169 break; 177 break;
170 case RPM_MSG_TYPE_ERR: 178 case RPM_MSG_TYPE_ERR:
171 len = min_t(u32, ALIGN(msg->length, 4), sizeof(msgbuf)); 179 len = min_t(u32, ALIGN(msg_length, 4), sizeof(msgbuf));
172 memcpy_fromio(msgbuf, msg->message, len); 180 memcpy_fromio(msgbuf, msg->message, len);
173 msgbuf[len - 1] = 0; 181 msgbuf[len - 1] = 0;
174 182
@@ -179,7 +187,7 @@ static int qcom_smd_rpm_callback(struct qcom_smd_device *qsdev,
179 break; 187 break;
180 } 188 }
181 189
182 buf = PTR_ALIGN(buf + 2 * sizeof(u32) + msg->length, 4); 190 buf = PTR_ALIGN(buf + 2 * sizeof(u32) + msg_length, 4);
183 } 191 }
184 192
185 rpm->ack_status = status; 193 rpm->ack_status = status;
diff --git a/drivers/soc/qcom/smd.c b/drivers/soc/qcom/smd.c
index a6155c917d52..86b598cff91a 100644
--- a/drivers/soc/qcom/smd.c
+++ b/drivers/soc/qcom/smd.c
@@ -65,7 +65,9 @@
65 */ 65 */
66 66
67struct smd_channel_info; 67struct smd_channel_info;
68struct smd_channel_info_pair;
68struct smd_channel_info_word; 69struct smd_channel_info_word;
70struct smd_channel_info_word_pair;
69 71
70#define SMD_ALLOC_TBL_COUNT 2 72#define SMD_ALLOC_TBL_COUNT 2
71#define SMD_ALLOC_TBL_SIZE 64 73#define SMD_ALLOC_TBL_SIZE 64
@@ -85,8 +87,8 @@ static const struct {
85 .fifo_base_id = 338 87 .fifo_base_id = 338
86 }, 88 },
87 { 89 {
88 .alloc_tbl_id = 14, 90 .alloc_tbl_id = 266,
89 .info_base_id = 266, 91 .info_base_id = 138,
90 .fifo_base_id = 202, 92 .fifo_base_id = 202,
91 }, 93 },
92}; 94};
@@ -151,10 +153,8 @@ enum smd_channel_state {
151 * @name: name of the channel 153 * @name: name of the channel
152 * @state: local state of the channel 154 * @state: local state of the channel
153 * @remote_state: remote state of the channel 155 * @remote_state: remote state of the channel
154 * @tx_info: byte aligned outgoing channel info 156 * @info: byte aligned outgoing/incoming channel info
155 * @rx_info: byte aligned incoming channel info 157 * @info_word: word aligned outgoing/incoming channel info
156 * @tx_info_word: word aligned outgoing channel info
157 * @rx_info_word: word aligned incoming channel info
158 * @tx_lock: lock to make writes to the channel mutually exclusive 158 * @tx_lock: lock to make writes to the channel mutually exclusive
159 * @fblockread_event: wakeup event tied to tx fBLOCKREADINTR 159 * @fblockread_event: wakeup event tied to tx fBLOCKREADINTR
160 * @tx_fifo: pointer to the outgoing ring buffer 160 * @tx_fifo: pointer to the outgoing ring buffer
@@ -175,11 +175,8 @@ struct qcom_smd_channel {
175 enum smd_channel_state state; 175 enum smd_channel_state state;
176 enum smd_channel_state remote_state; 176 enum smd_channel_state remote_state;
177 177
178 struct smd_channel_info *tx_info; 178 struct smd_channel_info_pair *info;
179 struct smd_channel_info *rx_info; 179 struct smd_channel_info_word_pair *info_word;
180
181 struct smd_channel_info_word *tx_info_word;
182 struct smd_channel_info_word *rx_info_word;
183 180
184 struct mutex tx_lock; 181 struct mutex tx_lock;
185 wait_queue_head_t fblockread_event; 182 wait_queue_head_t fblockread_event;
@@ -215,7 +212,7 @@ struct qcom_smd {
215 * Format of the smd_info smem items, for byte aligned channels. 212 * Format of the smd_info smem items, for byte aligned channels.
216 */ 213 */
217struct smd_channel_info { 214struct smd_channel_info {
218 u32 state; 215 __le32 state;
219 u8 fDSR; 216 u8 fDSR;
220 u8 fCTS; 217 u8 fCTS;
221 u8 fCD; 218 u8 fCD;
@@ -224,46 +221,104 @@ struct smd_channel_info {
224 u8 fTAIL; 221 u8 fTAIL;
225 u8 fSTATE; 222 u8 fSTATE;
226 u8 fBLOCKREADINTR; 223 u8 fBLOCKREADINTR;
227 u32 tail; 224 __le32 tail;
228 u32 head; 225 __le32 head;
226};
227
228struct smd_channel_info_pair {
229 struct smd_channel_info tx;
230 struct smd_channel_info rx;
229}; 231};
230 232
231/* 233/*
232 * Format of the smd_info smem items, for word aligned channels. 234 * Format of the smd_info smem items, for word aligned channels.
233 */ 235 */
234struct smd_channel_info_word { 236struct smd_channel_info_word {
235 u32 state; 237 __le32 state;
236 u32 fDSR; 238 __le32 fDSR;
237 u32 fCTS; 239 __le32 fCTS;
238 u32 fCD; 240 __le32 fCD;
239 u32 fRI; 241 __le32 fRI;
240 u32 fHEAD; 242 __le32 fHEAD;
241 u32 fTAIL; 243 __le32 fTAIL;
242 u32 fSTATE; 244 __le32 fSTATE;
243 u32 fBLOCKREADINTR; 245 __le32 fBLOCKREADINTR;
244 u32 tail; 246 __le32 tail;
245 u32 head; 247 __le32 head;
246}; 248};
247 249
248#define GET_RX_CHANNEL_INFO(channel, param) \ 250struct smd_channel_info_word_pair {
249 (channel->rx_info_word ? \ 251 struct smd_channel_info_word tx;
250 channel->rx_info_word->param : \ 252 struct smd_channel_info_word rx;
251 channel->rx_info->param) 253};
252
253#define SET_RX_CHANNEL_INFO(channel, param, value) \
254 (channel->rx_info_word ? \
255 (channel->rx_info_word->param = value) : \
256 (channel->rx_info->param = value))
257
258#define GET_TX_CHANNEL_INFO(channel, param) \
259 (channel->tx_info_word ? \
260 channel->tx_info_word->param : \
261 channel->tx_info->param)
262 254
263#define SET_TX_CHANNEL_INFO(channel, param, value) \ 255#define GET_RX_CHANNEL_FLAG(channel, param) \
264 (channel->tx_info_word ? \ 256 ({ \
265 (channel->tx_info_word->param = value) : \ 257 BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u8)); \
266 (channel->tx_info->param = value)) 258 channel->info_word ? \
259 le32_to_cpu(channel->info_word->rx.param) : \
260 channel->info->rx.param; \
261 })
262
263#define GET_RX_CHANNEL_INFO(channel, param) \
264 ({ \
265 BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u32)); \
266 le32_to_cpu(channel->info_word ? \
267 channel->info_word->rx.param : \
268 channel->info->rx.param); \
269 })
270
271#define SET_RX_CHANNEL_FLAG(channel, param, value) \
272 ({ \
273 BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u8)); \
274 if (channel->info_word) \
275 channel->info_word->rx.param = cpu_to_le32(value); \
276 else \
277 channel->info->rx.param = value; \
278 })
279
280#define SET_RX_CHANNEL_INFO(channel, param, value) \
281 ({ \
282 BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u32)); \
283 if (channel->info_word) \
284 channel->info_word->rx.param = cpu_to_le32(value); \
285 else \
286 channel->info->rx.param = cpu_to_le32(value); \
287 })
288
289#define GET_TX_CHANNEL_FLAG(channel, param) \
290 ({ \
291 BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u8)); \
292 channel->info_word ? \
293 le32_to_cpu(channel->info_word->tx.param) : \
294 channel->info->tx.param; \
295 })
296
297#define GET_TX_CHANNEL_INFO(channel, param) \
298 ({ \
299 BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u32)); \
300 le32_to_cpu(channel->info_word ? \
301 channel->info_word->tx.param : \
302 channel->info->tx.param); \
303 })
304
305#define SET_TX_CHANNEL_FLAG(channel, param, value) \
306 ({ \
307 BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u8)); \
308 if (channel->info_word) \
309 channel->info_word->tx.param = cpu_to_le32(value); \
310 else \
311 channel->info->tx.param = value; \
312 })
313
314#define SET_TX_CHANNEL_INFO(channel, param, value) \
315 ({ \
316 BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u32)); \
317 if (channel->info_word) \
318 channel->info_word->tx.param = cpu_to_le32(value); \
319 else \
320 channel->info->tx.param = cpu_to_le32(value); \
321 })
267 322
268/** 323/**
269 * struct qcom_smd_alloc_entry - channel allocation entry 324 * struct qcom_smd_alloc_entry - channel allocation entry
@@ -274,9 +329,9 @@ struct smd_channel_info_word {
274 */ 329 */
275struct qcom_smd_alloc_entry { 330struct qcom_smd_alloc_entry {
276 u8 name[20]; 331 u8 name[20];
277 u32 cid; 332 __le32 cid;
278 u32 flags; 333 __le32 flags;
279 u32 ref_count; 334 __le32 ref_count;
280} __packed; 335} __packed;
281 336
282#define SMD_CHANNEL_FLAGS_EDGE_MASK 0xff 337#define SMD_CHANNEL_FLAGS_EDGE_MASK 0xff
@@ -305,14 +360,14 @@ static void qcom_smd_signal_channel(struct qcom_smd_channel *channel)
305static void qcom_smd_channel_reset(struct qcom_smd_channel *channel) 360static void qcom_smd_channel_reset(struct qcom_smd_channel *channel)
306{ 361{
307 SET_TX_CHANNEL_INFO(channel, state, SMD_CHANNEL_CLOSED); 362 SET_TX_CHANNEL_INFO(channel, state, SMD_CHANNEL_CLOSED);
308 SET_TX_CHANNEL_INFO(channel, fDSR, 0); 363 SET_TX_CHANNEL_FLAG(channel, fDSR, 0);
309 SET_TX_CHANNEL_INFO(channel, fCTS, 0); 364 SET_TX_CHANNEL_FLAG(channel, fCTS, 0);
310 SET_TX_CHANNEL_INFO(channel, fCD, 0); 365 SET_TX_CHANNEL_FLAG(channel, fCD, 0);
311 SET_TX_CHANNEL_INFO(channel, fRI, 0); 366 SET_TX_CHANNEL_FLAG(channel, fRI, 0);
312 SET_TX_CHANNEL_INFO(channel, fHEAD, 0); 367 SET_TX_CHANNEL_FLAG(channel, fHEAD, 0);
313 SET_TX_CHANNEL_INFO(channel, fTAIL, 0); 368 SET_TX_CHANNEL_FLAG(channel, fTAIL, 0);
314 SET_TX_CHANNEL_INFO(channel, fSTATE, 1); 369 SET_TX_CHANNEL_FLAG(channel, fSTATE, 1);
315 SET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR, 1); 370 SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 1);
316 SET_TX_CHANNEL_INFO(channel, head, 0); 371 SET_TX_CHANNEL_INFO(channel, head, 0);
317 SET_TX_CHANNEL_INFO(channel, tail, 0); 372 SET_TX_CHANNEL_INFO(channel, tail, 0);
318 373
@@ -350,12 +405,12 @@ static void qcom_smd_channel_set_state(struct qcom_smd_channel *channel,
350 405
351 dev_dbg(edge->smd->dev, "set_state(%s, %d)\n", channel->name, state); 406 dev_dbg(edge->smd->dev, "set_state(%s, %d)\n", channel->name, state);
352 407
353 SET_TX_CHANNEL_INFO(channel, fDSR, is_open); 408 SET_TX_CHANNEL_FLAG(channel, fDSR, is_open);
354 SET_TX_CHANNEL_INFO(channel, fCTS, is_open); 409 SET_TX_CHANNEL_FLAG(channel, fCTS, is_open);
355 SET_TX_CHANNEL_INFO(channel, fCD, is_open); 410 SET_TX_CHANNEL_FLAG(channel, fCD, is_open);
356 411
357 SET_TX_CHANNEL_INFO(channel, state, state); 412 SET_TX_CHANNEL_INFO(channel, state, state);
358 SET_TX_CHANNEL_INFO(channel, fSTATE, 1); 413 SET_TX_CHANNEL_FLAG(channel, fSTATE, 1);
359 414
360 channel->state = state; 415 channel->state = state;
361 qcom_smd_signal_channel(channel); 416 qcom_smd_signal_channel(channel);
@@ -364,20 +419,15 @@ static void qcom_smd_channel_set_state(struct qcom_smd_channel *channel,
364/* 419/*
365 * Copy count bytes of data using 32bit accesses, if that's required. 420 * Copy count bytes of data using 32bit accesses, if that's required.
366 */ 421 */
367static void smd_copy_to_fifo(void __iomem *_dst, 422static void smd_copy_to_fifo(void __iomem *dst,
368 const void *_src, 423 const void *src,
369 size_t count, 424 size_t count,
370 bool word_aligned) 425 bool word_aligned)
371{ 426{
372 u32 *dst = (u32 *)_dst;
373 u32 *src = (u32 *)_src;
374
375 if (word_aligned) { 427 if (word_aligned) {
376 count /= sizeof(u32); 428 __iowrite32_copy(dst, src, count / sizeof(u32));
377 while (count--)
378 writel_relaxed(*src++, dst++);
379 } else { 429 } else {
380 memcpy_toio(_dst, _src, count); 430 memcpy_toio(dst, src, count);
381 } 431 }
382} 432}
383 433
@@ -395,7 +445,7 @@ static void smd_copy_from_fifo(void *_dst,
395 if (word_aligned) { 445 if (word_aligned) {
396 count /= sizeof(u32); 446 count /= sizeof(u32);
397 while (count--) 447 while (count--)
398 *dst++ = readl_relaxed(src++); 448 *dst++ = __raw_readl(src++);
399 } else { 449 } else {
400 memcpy_fromio(_dst, _src, count); 450 memcpy_fromio(_dst, _src, count);
401 } 451 }
@@ -412,7 +462,7 @@ static size_t qcom_smd_channel_peek(struct qcom_smd_channel *channel,
412 unsigned tail; 462 unsigned tail;
413 size_t len; 463 size_t len;
414 464
415 word_aligned = channel->rx_info_word != NULL; 465 word_aligned = channel->info_word;
416 tail = GET_RX_CHANNEL_INFO(channel, tail); 466 tail = GET_RX_CHANNEL_INFO(channel, tail);
417 467
418 len = min_t(size_t, count, channel->fifo_size - tail); 468 len = min_t(size_t, count, channel->fifo_size - tail);
@@ -491,7 +541,7 @@ static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel)
491{ 541{
492 bool need_state_scan = false; 542 bool need_state_scan = false;
493 int remote_state; 543 int remote_state;
494 u32 pktlen; 544 __le32 pktlen;
495 int avail; 545 int avail;
496 int ret; 546 int ret;
497 547
@@ -502,10 +552,10 @@ static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel)
502 need_state_scan = true; 552 need_state_scan = true;
503 } 553 }
504 /* Indicate that we have seen any state change */ 554 /* Indicate that we have seen any state change */
505 SET_RX_CHANNEL_INFO(channel, fSTATE, 0); 555 SET_RX_CHANNEL_FLAG(channel, fSTATE, 0);
506 556
507 /* Signal waiting qcom_smd_send() about the interrupt */ 557 /* Signal waiting qcom_smd_send() about the interrupt */
508 if (!GET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR)) 558 if (!GET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR))
509 wake_up_interruptible(&channel->fblockread_event); 559 wake_up_interruptible(&channel->fblockread_event);
510 560
511 /* Don't consume any data until we've opened the channel */ 561 /* Don't consume any data until we've opened the channel */
@@ -513,7 +563,7 @@ static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel)
513 goto out; 563 goto out;
514 564
515 /* Indicate that we've seen the new data */ 565 /* Indicate that we've seen the new data */
516 SET_RX_CHANNEL_INFO(channel, fHEAD, 0); 566 SET_RX_CHANNEL_FLAG(channel, fHEAD, 0);
517 567
518 /* Consume data */ 568 /* Consume data */
519 for (;;) { 569 for (;;) {
@@ -522,7 +572,7 @@ static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel)
522 if (!channel->pkt_size && avail >= SMD_PACKET_HEADER_LEN) { 572 if (!channel->pkt_size && avail >= SMD_PACKET_HEADER_LEN) {
523 qcom_smd_channel_peek(channel, &pktlen, sizeof(pktlen)); 573 qcom_smd_channel_peek(channel, &pktlen, sizeof(pktlen));
524 qcom_smd_channel_advance(channel, SMD_PACKET_HEADER_LEN); 574 qcom_smd_channel_advance(channel, SMD_PACKET_HEADER_LEN);
525 channel->pkt_size = pktlen; 575 channel->pkt_size = le32_to_cpu(pktlen);
526 } else if (channel->pkt_size && avail >= channel->pkt_size) { 576 } else if (channel->pkt_size && avail >= channel->pkt_size) {
527 ret = qcom_smd_channel_recv_single(channel); 577 ret = qcom_smd_channel_recv_single(channel);
528 if (ret) 578 if (ret)
@@ -533,10 +583,10 @@ static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel)
533 } 583 }
534 584
535 /* Indicate that we have seen and updated tail */ 585 /* Indicate that we have seen and updated tail */
536 SET_RX_CHANNEL_INFO(channel, fTAIL, 1); 586 SET_RX_CHANNEL_FLAG(channel, fTAIL, 1);
537 587
538 /* Signal the remote that we've consumed the data (if requested) */ 588 /* Signal the remote that we've consumed the data (if requested) */
539 if (!GET_RX_CHANNEL_INFO(channel, fBLOCKREADINTR)) { 589 if (!GET_RX_CHANNEL_FLAG(channel, fBLOCKREADINTR)) {
540 /* Ensure ordering of channel info updates */ 590 /* Ensure ordering of channel info updates */
541 wmb(); 591 wmb();
542 592
@@ -627,7 +677,7 @@ static int qcom_smd_write_fifo(struct qcom_smd_channel *channel,
627 unsigned head; 677 unsigned head;
628 size_t len; 678 size_t len;
629 679
630 word_aligned = channel->tx_info_word != NULL; 680 word_aligned = channel->info_word;
631 head = GET_TX_CHANNEL_INFO(channel, head); 681 head = GET_TX_CHANNEL_INFO(channel, head);
632 682
633 len = min_t(size_t, count, channel->fifo_size - head); 683 len = min_t(size_t, count, channel->fifo_size - head);
@@ -665,12 +715,16 @@ static int qcom_smd_write_fifo(struct qcom_smd_channel *channel,
665 */ 715 */
666int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len) 716int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len)
667{ 717{
668 u32 hdr[5] = {len,}; 718 __le32 hdr[5] = { cpu_to_le32(len), };
669 int tlen = sizeof(hdr) + len; 719 int tlen = sizeof(hdr) + len;
670 int ret; 720 int ret;
671 721
672 /* Word aligned channels only accept word size aligned data */ 722 /* Word aligned channels only accept word size aligned data */
673 if (channel->rx_info_word != NULL && len % 4) 723 if (channel->info_word && len % 4)
724 return -EINVAL;
725
726 /* Reject packets that are too big */
727 if (tlen >= channel->fifo_size)
674 return -EINVAL; 728 return -EINVAL;
675 729
676 ret = mutex_lock_interruptible(&channel->tx_lock); 730 ret = mutex_lock_interruptible(&channel->tx_lock);
@@ -683,7 +737,7 @@ int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len)
683 goto out; 737 goto out;
684 } 738 }
685 739
686 SET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR, 0); 740 SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 0);
687 741
688 ret = wait_event_interruptible(channel->fblockread_event, 742 ret = wait_event_interruptible(channel->fblockread_event,
689 qcom_smd_get_tx_avail(channel) >= tlen || 743 qcom_smd_get_tx_avail(channel) >= tlen ||
@@ -691,15 +745,15 @@ int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len)
691 if (ret) 745 if (ret)
692 goto out; 746 goto out;
693 747
694 SET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR, 1); 748 SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 1);
695 } 749 }
696 750
697 SET_TX_CHANNEL_INFO(channel, fTAIL, 0); 751 SET_TX_CHANNEL_FLAG(channel, fTAIL, 0);
698 752
699 qcom_smd_write_fifo(channel, hdr, sizeof(hdr)); 753 qcom_smd_write_fifo(channel, hdr, sizeof(hdr));
700 qcom_smd_write_fifo(channel, data, len); 754 qcom_smd_write_fifo(channel, data, len);
701 755
702 SET_TX_CHANNEL_INFO(channel, fHEAD, 1); 756 SET_TX_CHANNEL_FLAG(channel, fHEAD, 1);
703 757
704 /* Ensure ordering of channel info updates */ 758 /* Ensure ordering of channel info updates */
705 wmb(); 759 wmb();
@@ -727,6 +781,19 @@ static struct qcom_smd_driver *to_smd_driver(struct device *dev)
727 781
728static int qcom_smd_dev_match(struct device *dev, struct device_driver *drv) 782static int qcom_smd_dev_match(struct device *dev, struct device_driver *drv)
729{ 783{
784 struct qcom_smd_device *qsdev = to_smd_device(dev);
785 struct qcom_smd_driver *qsdrv = container_of(drv, struct qcom_smd_driver, driver);
786 const struct qcom_smd_id *match = qsdrv->smd_match_table;
787 const char *name = qsdev->channel->name;
788
789 if (match) {
790 while (match->name[0]) {
791 if (!strcmp(match->name, name))
792 return 1;
793 match++;
794 }
795 }
796
730 return of_driver_match_device(dev, drv); 797 return of_driver_match_device(dev, drv);
731} 798}
732 799
@@ -854,10 +921,8 @@ static struct device_node *qcom_smd_match_channel(struct device_node *edge_node,
854 for_each_available_child_of_node(edge_node, child) { 921 for_each_available_child_of_node(edge_node, child) {
855 key = "qcom,smd-channels"; 922 key = "qcom,smd-channels";
856 ret = of_property_read_string(child, key, &name); 923 ret = of_property_read_string(child, key, &name);
857 if (ret) { 924 if (ret)
858 of_node_put(child);
859 continue; 925 continue;
860 }
861 926
862 if (strcmp(name, channel) == 0) 927 if (strcmp(name, channel) == 0)
863 return child; 928 return child;
@@ -880,19 +945,17 @@ static int qcom_smd_create_device(struct qcom_smd_channel *channel)
880 if (channel->qsdev) 945 if (channel->qsdev)
881 return -EEXIST; 946 return -EEXIST;
882 947
883 node = qcom_smd_match_channel(edge->of_node, channel->name);
884 if (!node) {
885 dev_dbg(smd->dev, "no match for '%s'\n", channel->name);
886 return -ENXIO;
887 }
888
889 dev_dbg(smd->dev, "registering '%s'\n", channel->name); 948 dev_dbg(smd->dev, "registering '%s'\n", channel->name);
890 949
891 qsdev = kzalloc(sizeof(*qsdev), GFP_KERNEL); 950 qsdev = kzalloc(sizeof(*qsdev), GFP_KERNEL);
892 if (!qsdev) 951 if (!qsdev)
893 return -ENOMEM; 952 return -ENOMEM;
894 953
895 dev_set_name(&qsdev->dev, "%s.%s", edge->of_node->name, node->name); 954 node = qcom_smd_match_channel(edge->of_node, channel->name);
955 dev_set_name(&qsdev->dev, "%s.%s",
956 edge->of_node->name,
957 node ? node->name : channel->name);
958
896 qsdev->dev.parent = smd->dev; 959 qsdev->dev.parent = smd->dev;
897 qsdev->dev.bus = &qcom_smd_bus; 960 qsdev->dev.bus = &qcom_smd_bus;
898 qsdev->dev.release = qcom_smd_release_device; 961 qsdev->dev.release = qcom_smd_release_device;
@@ -978,21 +1041,20 @@ static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *ed
978 spin_lock_init(&channel->recv_lock); 1041 spin_lock_init(&channel->recv_lock);
979 init_waitqueue_head(&channel->fblockread_event); 1042 init_waitqueue_head(&channel->fblockread_event);
980 1043
981 ret = qcom_smem_get(edge->remote_pid, smem_info_item, (void **)&info, 1044 info = qcom_smem_get(edge->remote_pid, smem_info_item, &info_size);
982 &info_size); 1045 if (IS_ERR(info)) {
983 if (ret) 1046 ret = PTR_ERR(info);
984 goto free_name_and_channel; 1047 goto free_name_and_channel;
1048 }
985 1049
986 /* 1050 /*
987 * Use the size of the item to figure out which channel info struct to 1051 * Use the size of the item to figure out which channel info struct to
988 * use. 1052 * use.
989 */ 1053 */
990 if (info_size == 2 * sizeof(struct smd_channel_info_word)) { 1054 if (info_size == 2 * sizeof(struct smd_channel_info_word)) {
991 channel->tx_info_word = info; 1055 channel->info_word = info;
992 channel->rx_info_word = info + sizeof(struct smd_channel_info_word);
993 } else if (info_size == 2 * sizeof(struct smd_channel_info)) { 1056 } else if (info_size == 2 * sizeof(struct smd_channel_info)) {
994 channel->tx_info = info; 1057 channel->info = info;
995 channel->rx_info = info + sizeof(struct smd_channel_info);
996 } else { 1058 } else {
997 dev_err(smd->dev, 1059 dev_err(smd->dev,
998 "channel info of size %zu not supported\n", info_size); 1060 "channel info of size %zu not supported\n", info_size);
@@ -1000,10 +1062,11 @@ static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *ed
1000 goto free_name_and_channel; 1062 goto free_name_and_channel;
1001 } 1063 }
1002 1064
1003 ret = qcom_smem_get(edge->remote_pid, smem_fifo_item, &fifo_base, 1065 fifo_base = qcom_smem_get(edge->remote_pid, smem_fifo_item, &fifo_size);
1004 &fifo_size); 1066 if (IS_ERR(fifo_base)) {
1005 if (ret) 1067 ret = PTR_ERR(fifo_base);
1006 goto free_name_and_channel; 1068 goto free_name_and_channel;
1069 }
1007 1070
1008 /* The channel consist of a rx and tx fifo of equal size */ 1071 /* The channel consist of a rx and tx fifo of equal size */
1009 fifo_size /= 2; 1072 fifo_size /= 2;
@@ -1040,20 +1103,19 @@ static void qcom_discover_channels(struct qcom_smd_edge *edge)
1040 unsigned long flags; 1103 unsigned long flags;
1041 unsigned fifo_id; 1104 unsigned fifo_id;
1042 unsigned info_id; 1105 unsigned info_id;
1043 int ret;
1044 int tbl; 1106 int tbl;
1045 int i; 1107 int i;
1108 u32 eflags, cid;
1046 1109
1047 for (tbl = 0; tbl < SMD_ALLOC_TBL_COUNT; tbl++) { 1110 for (tbl = 0; tbl < SMD_ALLOC_TBL_COUNT; tbl++) {
1048 ret = qcom_smem_get(edge->remote_pid, 1111 alloc_tbl = qcom_smem_get(edge->remote_pid,
1049 smem_items[tbl].alloc_tbl_id, 1112 smem_items[tbl].alloc_tbl_id, NULL);
1050 (void **)&alloc_tbl, 1113 if (IS_ERR(alloc_tbl))
1051 NULL);
1052 if (ret < 0)
1053 continue; 1114 continue;
1054 1115
1055 for (i = 0; i < SMD_ALLOC_TBL_SIZE; i++) { 1116 for (i = 0; i < SMD_ALLOC_TBL_SIZE; i++) {
1056 entry = &alloc_tbl[i]; 1117 entry = &alloc_tbl[i];
1118 eflags = le32_to_cpu(entry->flags);
1057 if (test_bit(i, edge->allocated[tbl])) 1119 if (test_bit(i, edge->allocated[tbl]))
1058 continue; 1120 continue;
1059 1121
@@ -1063,14 +1125,15 @@ static void qcom_discover_channels(struct qcom_smd_edge *edge)
1063 if (!entry->name[0]) 1125 if (!entry->name[0])
1064 continue; 1126 continue;
1065 1127
1066 if (!(entry->flags & SMD_CHANNEL_FLAGS_PACKET)) 1128 if (!(eflags & SMD_CHANNEL_FLAGS_PACKET))
1067 continue; 1129 continue;
1068 1130
1069 if ((entry->flags & SMD_CHANNEL_FLAGS_EDGE_MASK) != edge->edge_id) 1131 if ((eflags & SMD_CHANNEL_FLAGS_EDGE_MASK) != edge->edge_id)
1070 continue; 1132 continue;
1071 1133
1072 info_id = smem_items[tbl].info_base_id + entry->cid; 1134 cid = le32_to_cpu(entry->cid);
1073 fifo_id = smem_items[tbl].fifo_base_id + entry->cid; 1135 info_id = smem_items[tbl].info_base_id + cid;
1136 fifo_id = smem_items[tbl].fifo_base_id + cid;
1074 1137
1075 channel = qcom_smd_create_channel(edge, info_id, fifo_id, entry->name); 1138 channel = qcom_smd_create_channel(edge, info_id, fifo_id, entry->name);
1076 if (IS_ERR(channel)) 1139 if (IS_ERR(channel))
@@ -1227,11 +1290,12 @@ static int qcom_smd_probe(struct platform_device *pdev)
1227 int num_edges; 1290 int num_edges;
1228 int ret; 1291 int ret;
1229 int i = 0; 1292 int i = 0;
1293 void *p;
1230 1294
1231 /* Wait for smem */ 1295 /* Wait for smem */
1232 ret = qcom_smem_get(QCOM_SMEM_HOST_ANY, smem_items[0].alloc_tbl_id, NULL, NULL); 1296 p = qcom_smem_get(QCOM_SMEM_HOST_ANY, smem_items[0].alloc_tbl_id, NULL);
1233 if (ret == -EPROBE_DEFER) 1297 if (PTR_ERR(p) == -EPROBE_DEFER)
1234 return ret; 1298 return PTR_ERR(p);
1235 1299
1236 num_edges = of_get_available_child_count(pdev->dev.of_node); 1300 num_edges = of_get_available_child_count(pdev->dev.of_node);
1237 array_size = sizeof(*smd) + num_edges * sizeof(struct qcom_smd_edge); 1301 array_size = sizeof(*smd) + num_edges * sizeof(struct qcom_smd_edge);
diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c
index 52365188a1c2..19019aa092e8 100644
--- a/drivers/soc/qcom/smem.c
+++ b/drivers/soc/qcom/smem.c
@@ -92,9 +92,9 @@
92 * @params: parameters to the command 92 * @params: parameters to the command
93 */ 93 */
94struct smem_proc_comm { 94struct smem_proc_comm {
95 u32 command; 95 __le32 command;
96 u32 status; 96 __le32 status;
97 u32 params[2]; 97 __le32 params[2];
98}; 98};
99 99
100/** 100/**
@@ -106,10 +106,10 @@ struct smem_proc_comm {
106 * the default region. bits 0,1 are reserved 106 * the default region. bits 0,1 are reserved
107 */ 107 */
108struct smem_global_entry { 108struct smem_global_entry {
109 u32 allocated; 109 __le32 allocated;
110 u32 offset; 110 __le32 offset;
111 u32 size; 111 __le32 size;
112 u32 aux_base; /* bits 1:0 reserved */ 112 __le32 aux_base; /* bits 1:0 reserved */
113}; 113};
114#define AUX_BASE_MASK 0xfffffffc 114#define AUX_BASE_MASK 0xfffffffc
115 115
@@ -125,11 +125,11 @@ struct smem_global_entry {
125 */ 125 */
126struct smem_header { 126struct smem_header {
127 struct smem_proc_comm proc_comm[4]; 127 struct smem_proc_comm proc_comm[4];
128 u32 version[32]; 128 __le32 version[32];
129 u32 initialized; 129 __le32 initialized;
130 u32 free_offset; 130 __le32 free_offset;
131 u32 available; 131 __le32 available;
132 u32 reserved; 132 __le32 reserved;
133 struct smem_global_entry toc[SMEM_ITEM_COUNT]; 133 struct smem_global_entry toc[SMEM_ITEM_COUNT];
134}; 134};
135 135
@@ -143,12 +143,12 @@ struct smem_header {
143 * @reserved: reserved entries for later use 143 * @reserved: reserved entries for later use
144 */ 144 */
145struct smem_ptable_entry { 145struct smem_ptable_entry {
146 u32 offset; 146 __le32 offset;
147 u32 size; 147 __le32 size;
148 u32 flags; 148 __le32 flags;
149 u16 host0; 149 __le16 host0;
150 u16 host1; 150 __le16 host1;
151 u32 reserved[8]; 151 __le32 reserved[8];
152}; 152};
153 153
154/** 154/**
@@ -160,13 +160,14 @@ struct smem_ptable_entry {
160 * @entry: list of @smem_ptable_entry for the @num_entries partitions 160 * @entry: list of @smem_ptable_entry for the @num_entries partitions
161 */ 161 */
162struct smem_ptable { 162struct smem_ptable {
163 u32 magic; 163 u8 magic[4];
164 u32 version; 164 __le32 version;
165 u32 num_entries; 165 __le32 num_entries;
166 u32 reserved[5]; 166 __le32 reserved[5];
167 struct smem_ptable_entry entry[]; 167 struct smem_ptable_entry entry[];
168}; 168};
169#define SMEM_PTABLE_MAGIC 0x434f5424 /* "$TOC" */ 169
170static const u8 SMEM_PTABLE_MAGIC[] = { 0x24, 0x54, 0x4f, 0x43 }; /* "$TOC" */
170 171
171/** 172/**
172 * struct smem_partition_header - header of the partitions 173 * struct smem_partition_header - header of the partitions
@@ -181,15 +182,16 @@ struct smem_ptable {
181 * @reserved: for now reserved entries 182 * @reserved: for now reserved entries
182 */ 183 */
183struct smem_partition_header { 184struct smem_partition_header {
184 u32 magic; 185 u8 magic[4];
185 u16 host0; 186 __le16 host0;
186 u16 host1; 187 __le16 host1;
187 u32 size; 188 __le32 size;
188 u32 offset_free_uncached; 189 __le32 offset_free_uncached;
189 u32 offset_free_cached; 190 __le32 offset_free_cached;
190 u32 reserved[3]; 191 __le32 reserved[3];
191}; 192};
192#define SMEM_PART_MAGIC 0x54525024 /* "$PRT" */ 193
194static const u8 SMEM_PART_MAGIC[] = { 0x24, 0x50, 0x52, 0x54 };
193 195
194/** 196/**
195 * struct smem_private_entry - header of each item in the private partition 197 * struct smem_private_entry - header of each item in the private partition
@@ -201,12 +203,12 @@ struct smem_partition_header {
201 * @reserved: for now reserved entry 203 * @reserved: for now reserved entry
202 */ 204 */
203struct smem_private_entry { 205struct smem_private_entry {
204 u16 canary; 206 u16 canary; /* bytes are the same so no swapping needed */
205 u16 item; 207 __le16 item;
206 u32 size; /* includes padding bytes */ 208 __le32 size; /* includes padding bytes */
207 u16 padding_data; 209 __le16 padding_data;
208 u16 padding_hdr; 210 __le16 padding_hdr;
209 u32 reserved; 211 __le32 reserved;
210}; 212};
211#define SMEM_PRIVATE_CANARY 0xa5a5 213#define SMEM_PRIVATE_CANARY 0xa5a5
212 214
@@ -242,6 +244,45 @@ struct qcom_smem {
242 struct smem_region regions[0]; 244 struct smem_region regions[0];
243}; 245};
244 246
247static struct smem_private_entry *
248phdr_to_last_private_entry(struct smem_partition_header *phdr)
249{
250 void *p = phdr;
251
252 return p + le32_to_cpu(phdr->offset_free_uncached);
253}
254
255static void *phdr_to_first_cached_entry(struct smem_partition_header *phdr)
256{
257 void *p = phdr;
258
259 return p + le32_to_cpu(phdr->offset_free_cached);
260}
261
262static struct smem_private_entry *
263phdr_to_first_private_entry(struct smem_partition_header *phdr)
264{
265 void *p = phdr;
266
267 return p + sizeof(*phdr);
268}
269
270static struct smem_private_entry *
271private_entry_next(struct smem_private_entry *e)
272{
273 void *p = e;
274
275 return p + sizeof(*e) + le16_to_cpu(e->padding_hdr) +
276 le32_to_cpu(e->size);
277}
278
279static void *entry_to_item(struct smem_private_entry *e)
280{
281 void *p = e;
282
283 return p + sizeof(*e) + le16_to_cpu(e->padding_hdr);
284}
285
245/* Pointer to the one and only smem handle */ 286/* Pointer to the one and only smem handle */
246static struct qcom_smem *__smem; 287static struct qcom_smem *__smem;
247 288
@@ -254,16 +295,16 @@ static int qcom_smem_alloc_private(struct qcom_smem *smem,
254 size_t size) 295 size_t size)
255{ 296{
256 struct smem_partition_header *phdr; 297 struct smem_partition_header *phdr;
257 struct smem_private_entry *hdr; 298 struct smem_private_entry *hdr, *end;
258 size_t alloc_size; 299 size_t alloc_size;
259 void *p; 300 void *cached;
260 301
261 phdr = smem->partitions[host]; 302 phdr = smem->partitions[host];
303 hdr = phdr_to_first_private_entry(phdr);
304 end = phdr_to_last_private_entry(phdr);
305 cached = phdr_to_first_cached_entry(phdr);
262 306
263 p = (void *)phdr + sizeof(*phdr); 307 while (hdr < end) {
264 while (p < (void *)phdr + phdr->offset_free_uncached) {
265 hdr = p;
266
267 if (hdr->canary != SMEM_PRIVATE_CANARY) { 308 if (hdr->canary != SMEM_PRIVATE_CANARY) {
268 dev_err(smem->dev, 309 dev_err(smem->dev,
269 "Found invalid canary in host %d partition\n", 310 "Found invalid canary in host %d partition\n",
@@ -271,24 +312,23 @@ static int qcom_smem_alloc_private(struct qcom_smem *smem,
271 return -EINVAL; 312 return -EINVAL;
272 } 313 }
273 314
274 if (hdr->item == item) 315 if (le16_to_cpu(hdr->item) == item)
275 return -EEXIST; 316 return -EEXIST;
276 317
277 p += sizeof(*hdr) + hdr->padding_hdr + hdr->size; 318 hdr = private_entry_next(hdr);
278 } 319 }
279 320
280 /* Check that we don't grow into the cached region */ 321 /* Check that we don't grow into the cached region */
281 alloc_size = sizeof(*hdr) + ALIGN(size, 8); 322 alloc_size = sizeof(*hdr) + ALIGN(size, 8);
282 if (p + alloc_size >= (void *)phdr + phdr->offset_free_cached) { 323 if ((void *)hdr + alloc_size >= cached) {
283 dev_err(smem->dev, "Out of memory\n"); 324 dev_err(smem->dev, "Out of memory\n");
284 return -ENOSPC; 325 return -ENOSPC;
285 } 326 }
286 327
287 hdr = p;
288 hdr->canary = SMEM_PRIVATE_CANARY; 328 hdr->canary = SMEM_PRIVATE_CANARY;
289 hdr->item = item; 329 hdr->item = cpu_to_le16(item);
290 hdr->size = ALIGN(size, 8); 330 hdr->size = cpu_to_le32(ALIGN(size, 8));
291 hdr->padding_data = hdr->size - size; 331 hdr->padding_data = cpu_to_le16(le32_to_cpu(hdr->size) - size);
292 hdr->padding_hdr = 0; 332 hdr->padding_hdr = 0;
293 333
294 /* 334 /*
@@ -297,7 +337,7 @@ static int qcom_smem_alloc_private(struct qcom_smem *smem,
297 * gets a consistent view of the linked list. 337 * gets a consistent view of the linked list.
298 */ 338 */
299 wmb(); 339 wmb();
300 phdr->offset_free_uncached += alloc_size; 340 le32_add_cpu(&phdr->offset_free_uncached, alloc_size);
301 341
302 return 0; 342 return 0;
303} 343}
@@ -318,11 +358,11 @@ static int qcom_smem_alloc_global(struct qcom_smem *smem,
318 return -EEXIST; 358 return -EEXIST;
319 359
320 size = ALIGN(size, 8); 360 size = ALIGN(size, 8);
321 if (WARN_ON(size > header->available)) 361 if (WARN_ON(size > le32_to_cpu(header->available)))
322 return -ENOMEM; 362 return -ENOMEM;
323 363
324 entry->offset = header->free_offset; 364 entry->offset = header->free_offset;
325 entry->size = size; 365 entry->size = cpu_to_le32(size);
326 366
327 /* 367 /*
328 * Ensure the header is consistent before we mark the item allocated, 368 * Ensure the header is consistent before we mark the item allocated,
@@ -330,10 +370,10 @@ static int qcom_smem_alloc_global(struct qcom_smem *smem,
330 * even though they do not take the spinlock on read. 370 * even though they do not take the spinlock on read.
331 */ 371 */
332 wmb(); 372 wmb();
333 entry->allocated = 1; 373 entry->allocated = cpu_to_le32(1);
334 374
335 header->free_offset += size; 375 le32_add_cpu(&header->free_offset, size);
336 header->available -= size; 376 le32_add_cpu(&header->available, -size);
337 377
338 return 0; 378 return 0;
339} 379}
@@ -378,10 +418,9 @@ int qcom_smem_alloc(unsigned host, unsigned item, size_t size)
378} 418}
379EXPORT_SYMBOL(qcom_smem_alloc); 419EXPORT_SYMBOL(qcom_smem_alloc);
380 420
381static int qcom_smem_get_global(struct qcom_smem *smem, 421static void *qcom_smem_get_global(struct qcom_smem *smem,
382 unsigned item, 422 unsigned item,
383 void **ptr, 423 size_t *size)
384 size_t *size)
385{ 424{
386 struct smem_header *header; 425 struct smem_header *header;
387 struct smem_region *area; 426 struct smem_region *area;
@@ -390,100 +429,94 @@ static int qcom_smem_get_global(struct qcom_smem *smem,
390 unsigned i; 429 unsigned i;
391 430
392 if (WARN_ON(item >= SMEM_ITEM_COUNT)) 431 if (WARN_ON(item >= SMEM_ITEM_COUNT))
393 return -EINVAL; 432 return ERR_PTR(-EINVAL);
394 433
395 header = smem->regions[0].virt_base; 434 header = smem->regions[0].virt_base;
396 entry = &header->toc[item]; 435 entry = &header->toc[item];
397 if (!entry->allocated) 436 if (!entry->allocated)
398 return -ENXIO; 437 return ERR_PTR(-ENXIO);
399 438
400 if (ptr != NULL) { 439 aux_base = le32_to_cpu(entry->aux_base) & AUX_BASE_MASK;
401 aux_base = entry->aux_base & AUX_BASE_MASK;
402 440
403 for (i = 0; i < smem->num_regions; i++) { 441 for (i = 0; i < smem->num_regions; i++) {
404 area = &smem->regions[i]; 442 area = &smem->regions[i];
405 443
406 if (area->aux_base == aux_base || !aux_base) { 444 if (area->aux_base == aux_base || !aux_base) {
407 *ptr = area->virt_base + entry->offset; 445 if (size != NULL)
408 break; 446 *size = le32_to_cpu(entry->size);
409 } 447 return area->virt_base + le32_to_cpu(entry->offset);
410 } 448 }
411 } 449 }
412 if (size != NULL)
413 *size = entry->size;
414 450
415 return 0; 451 return ERR_PTR(-ENOENT);
416} 452}
417 453
418static int qcom_smem_get_private(struct qcom_smem *smem, 454static void *qcom_smem_get_private(struct qcom_smem *smem,
419 unsigned host, 455 unsigned host,
420 unsigned item, 456 unsigned item,
421 void **ptr, 457 size_t *size)
422 size_t *size)
423{ 458{
424 struct smem_partition_header *phdr; 459 struct smem_partition_header *phdr;
425 struct smem_private_entry *hdr; 460 struct smem_private_entry *e, *end;
426 void *p;
427 461
428 phdr = smem->partitions[host]; 462 phdr = smem->partitions[host];
463 e = phdr_to_first_private_entry(phdr);
464 end = phdr_to_last_private_entry(phdr);
429 465
430 p = (void *)phdr + sizeof(*phdr); 466 while (e < end) {
431 while (p < (void *)phdr + phdr->offset_free_uncached) { 467 if (e->canary != SMEM_PRIVATE_CANARY) {
432 hdr = p;
433
434 if (hdr->canary != SMEM_PRIVATE_CANARY) {
435 dev_err(smem->dev, 468 dev_err(smem->dev,
436 "Found invalid canary in host %d partition\n", 469 "Found invalid canary in host %d partition\n",
437 host); 470 host);
438 return -EINVAL; 471 return ERR_PTR(-EINVAL);
439 } 472 }
440 473
441 if (hdr->item == item) { 474 if (le16_to_cpu(e->item) == item) {
442 if (ptr != NULL)
443 *ptr = p + sizeof(*hdr) + hdr->padding_hdr;
444
445 if (size != NULL) 475 if (size != NULL)
446 *size = hdr->size - hdr->padding_data; 476 *size = le32_to_cpu(e->size) -
477 le16_to_cpu(e->padding_data);
447 478
448 return 0; 479 return entry_to_item(e);
449 } 480 }
450 481
451 p += sizeof(*hdr) + hdr->padding_hdr + hdr->size; 482 e = private_entry_next(e);
452 } 483 }
453 484
454 return -ENOENT; 485 return ERR_PTR(-ENOENT);
455} 486}
456 487
457/** 488/**
458 * qcom_smem_get() - resolve ptr of size of a smem item 489 * qcom_smem_get() - resolve ptr of size of a smem item
459 * @host: the remote processor, or -1 490 * @host: the remote processor, or -1
460 * @item: smem item handle 491 * @item: smem item handle
461 * @ptr: pointer to be filled out with address of the item
462 * @size: pointer to be filled out with size of the item 492 * @size: pointer to be filled out with size of the item
463 * 493 *
464 * Looks up pointer and size of a smem item. 494 * Looks up smem item and returns pointer to it. Size of smem
495 * item is returned in @size.
465 */ 496 */
466int qcom_smem_get(unsigned host, unsigned item, void **ptr, size_t *size) 497void *qcom_smem_get(unsigned host, unsigned item, size_t *size)
467{ 498{
468 unsigned long flags; 499 unsigned long flags;
469 int ret; 500 int ret;
501 void *ptr = ERR_PTR(-EPROBE_DEFER);
470 502
471 if (!__smem) 503 if (!__smem)
472 return -EPROBE_DEFER; 504 return ptr;
473 505
474 ret = hwspin_lock_timeout_irqsave(__smem->hwlock, 506 ret = hwspin_lock_timeout_irqsave(__smem->hwlock,
475 HWSPINLOCK_TIMEOUT, 507 HWSPINLOCK_TIMEOUT,
476 &flags); 508 &flags);
477 if (ret) 509 if (ret)
478 return ret; 510 return ERR_PTR(ret);
479 511
480 if (host < SMEM_HOST_COUNT && __smem->partitions[host]) 512 if (host < SMEM_HOST_COUNT && __smem->partitions[host])
481 ret = qcom_smem_get_private(__smem, host, item, ptr, size); 513 ptr = qcom_smem_get_private(__smem, host, item, size);
482 else 514 else
483 ret = qcom_smem_get_global(__smem, item, ptr, size); 515 ptr = qcom_smem_get_global(__smem, item, size);
484 516
485 hwspin_unlock_irqrestore(__smem->hwlock, &flags); 517 hwspin_unlock_irqrestore(__smem->hwlock, &flags);
486 return ret; 518
519 return ptr;
487 520
488} 521}
489EXPORT_SYMBOL(qcom_smem_get); 522EXPORT_SYMBOL(qcom_smem_get);
@@ -506,10 +539,11 @@ int qcom_smem_get_free_space(unsigned host)
506 539
507 if (host < SMEM_HOST_COUNT && __smem->partitions[host]) { 540 if (host < SMEM_HOST_COUNT && __smem->partitions[host]) {
508 phdr = __smem->partitions[host]; 541 phdr = __smem->partitions[host];
509 ret = phdr->offset_free_cached - phdr->offset_free_uncached; 542 ret = le32_to_cpu(phdr->offset_free_cached) -
543 le32_to_cpu(phdr->offset_free_uncached);
510 } else { 544 } else {
511 header = __smem->regions[0].virt_base; 545 header = __smem->regions[0].virt_base;
512 ret = header->available; 546 ret = le32_to_cpu(header->available);
513 } 547 }
514 548
515 return ret; 549 return ret;
@@ -518,13 +552,11 @@ EXPORT_SYMBOL(qcom_smem_get_free_space);
518 552
519static int qcom_smem_get_sbl_version(struct qcom_smem *smem) 553static int qcom_smem_get_sbl_version(struct qcom_smem *smem)
520{ 554{
521 unsigned *versions; 555 __le32 *versions;
522 size_t size; 556 size_t size;
523 int ret;
524 557
525 ret = qcom_smem_get_global(smem, SMEM_ITEM_VERSION, 558 versions = qcom_smem_get_global(smem, SMEM_ITEM_VERSION, &size);
526 (void **)&versions, &size); 559 if (IS_ERR(versions)) {
527 if (ret < 0) {
528 dev_err(smem->dev, "Unable to read the version item\n"); 560 dev_err(smem->dev, "Unable to read the version item\n");
529 return -ENOENT; 561 return -ENOENT;
530 } 562 }
@@ -534,7 +566,7 @@ static int qcom_smem_get_sbl_version(struct qcom_smem *smem)
534 return -EINVAL; 566 return -EINVAL;
535 } 567 }
536 568
537 return versions[SMEM_MASTER_SBL_VERSION_INDEX]; 569 return le32_to_cpu(versions[SMEM_MASTER_SBL_VERSION_INDEX]);
538} 570}
539 571
540static int qcom_smem_enumerate_partitions(struct qcom_smem *smem, 572static int qcom_smem_enumerate_partitions(struct qcom_smem *smem,
@@ -544,35 +576,38 @@ static int qcom_smem_enumerate_partitions(struct qcom_smem *smem,
544 struct smem_ptable_entry *entry; 576 struct smem_ptable_entry *entry;
545 struct smem_ptable *ptable; 577 struct smem_ptable *ptable;
546 unsigned remote_host; 578 unsigned remote_host;
579 u32 version, host0, host1;
547 int i; 580 int i;
548 581
549 ptable = smem->regions[0].virt_base + smem->regions[0].size - SZ_4K; 582 ptable = smem->regions[0].virt_base + smem->regions[0].size - SZ_4K;
550 if (ptable->magic != SMEM_PTABLE_MAGIC) 583 if (memcmp(ptable->magic, SMEM_PTABLE_MAGIC, sizeof(ptable->magic)))
551 return 0; 584 return 0;
552 585
553 if (ptable->version != 1) { 586 version = le32_to_cpu(ptable->version);
587 if (version != 1) {
554 dev_err(smem->dev, 588 dev_err(smem->dev,
555 "Unsupported partition header version %d\n", 589 "Unsupported partition header version %d\n", version);
556 ptable->version);
557 return -EINVAL; 590 return -EINVAL;
558 } 591 }
559 592
560 for (i = 0; i < ptable->num_entries; i++) { 593 for (i = 0; i < le32_to_cpu(ptable->num_entries); i++) {
561 entry = &ptable->entry[i]; 594 entry = &ptable->entry[i];
595 host0 = le16_to_cpu(entry->host0);
596 host1 = le16_to_cpu(entry->host1);
562 597
563 if (entry->host0 != local_host && entry->host1 != local_host) 598 if (host0 != local_host && host1 != local_host)
564 continue; 599 continue;
565 600
566 if (!entry->offset) 601 if (!le32_to_cpu(entry->offset))
567 continue; 602 continue;
568 603
569 if (!entry->size) 604 if (!le32_to_cpu(entry->size))
570 continue; 605 continue;
571 606
572 if (entry->host0 == local_host) 607 if (host0 == local_host)
573 remote_host = entry->host1; 608 remote_host = host1;
574 else 609 else
575 remote_host = entry->host0; 610 remote_host = host0;
576 611
577 if (remote_host >= SMEM_HOST_COUNT) { 612 if (remote_host >= SMEM_HOST_COUNT) {
578 dev_err(smem->dev, 613 dev_err(smem->dev,
@@ -588,21 +623,24 @@ static int qcom_smem_enumerate_partitions(struct qcom_smem *smem,
588 return -EINVAL; 623 return -EINVAL;
589 } 624 }
590 625
591 header = smem->regions[0].virt_base + entry->offset; 626 header = smem->regions[0].virt_base + le32_to_cpu(entry->offset);
627 host0 = le16_to_cpu(header->host0);
628 host1 = le16_to_cpu(header->host1);
592 629
593 if (header->magic != SMEM_PART_MAGIC) { 630 if (memcmp(header->magic, SMEM_PART_MAGIC,
631 sizeof(header->magic))) {
594 dev_err(smem->dev, 632 dev_err(smem->dev,
595 "Partition %d has invalid magic\n", i); 633 "Partition %d has invalid magic\n", i);
596 return -EINVAL; 634 return -EINVAL;
597 } 635 }
598 636
599 if (header->host0 != local_host && header->host1 != local_host) { 637 if (host0 != local_host && host1 != local_host) {
600 dev_err(smem->dev, 638 dev_err(smem->dev,
601 "Partition %d hosts are invalid\n", i); 639 "Partition %d hosts are invalid\n", i);
602 return -EINVAL; 640 return -EINVAL;
603 } 641 }
604 642
605 if (header->host0 != remote_host && header->host1 != remote_host) { 643 if (host0 != remote_host && host1 != remote_host) {
606 dev_err(smem->dev, 644 dev_err(smem->dev,
607 "Partition %d hosts are invalid\n", i); 645 "Partition %d hosts are invalid\n", i);
608 return -EINVAL; 646 return -EINVAL;
@@ -614,7 +652,7 @@ static int qcom_smem_enumerate_partitions(struct qcom_smem *smem,
614 return -EINVAL; 652 return -EINVAL;
615 } 653 }
616 654
617 if (header->offset_free_uncached > header->size) { 655 if (le32_to_cpu(header->offset_free_uncached) > le32_to_cpu(header->size)) {
618 dev_err(smem->dev, 656 dev_err(smem->dev,
619 "Partition %d has invalid free pointer\n", i); 657 "Partition %d has invalid free pointer\n", i);
620 return -EINVAL; 658 return -EINVAL;
@@ -626,37 +664,47 @@ static int qcom_smem_enumerate_partitions(struct qcom_smem *smem,
626 return 0; 664 return 0;
627} 665}
628 666
629static int qcom_smem_count_mem_regions(struct platform_device *pdev) 667static int qcom_smem_map_memory(struct qcom_smem *smem, struct device *dev,
668 const char *name, int i)
630{ 669{
631 struct resource *res; 670 struct device_node *np;
632 int num_regions = 0; 671 struct resource r;
633 int i; 672 int ret;
634
635 for (i = 0; i < pdev->num_resources; i++) {
636 res = &pdev->resource[i];
637 673
638 if (resource_type(res) == IORESOURCE_MEM) 674 np = of_parse_phandle(dev->of_node, name, 0);
639 num_regions++; 675 if (!np) {
676 dev_err(dev, "No %s specified\n", name);
677 return -EINVAL;
640 } 678 }
641 679
642 return num_regions; 680 ret = of_address_to_resource(np, 0, &r);
681 of_node_put(np);
682 if (ret)
683 return ret;
684
685 smem->regions[i].aux_base = (u32)r.start;
686 smem->regions[i].size = resource_size(&r);
687 smem->regions[i].virt_base = devm_ioremap_nocache(dev, r.start,
688 resource_size(&r));
689 if (!smem->regions[i].virt_base)
690 return -ENOMEM;
691
692 return 0;
643} 693}
644 694
645static int qcom_smem_probe(struct platform_device *pdev) 695static int qcom_smem_probe(struct platform_device *pdev)
646{ 696{
647 struct smem_header *header; 697 struct smem_header *header;
648 struct device_node *np;
649 struct qcom_smem *smem; 698 struct qcom_smem *smem;
650 struct resource *res;
651 struct resource r;
652 size_t array_size; 699 size_t array_size;
653 int num_regions = 0; 700 int num_regions;
654 int hwlock_id; 701 int hwlock_id;
655 u32 version; 702 u32 version;
656 int ret; 703 int ret;
657 int i;
658 704
659 num_regions = qcom_smem_count_mem_regions(pdev) + 1; 705 num_regions = 1;
706 if (of_find_property(pdev->dev.of_node, "qcom,rpm-msg-ram", NULL))
707 num_regions++;
660 708
661 array_size = num_regions * sizeof(struct smem_region); 709 array_size = num_regions * sizeof(struct smem_region);
662 smem = devm_kzalloc(&pdev->dev, sizeof(*smem) + array_size, GFP_KERNEL); 710 smem = devm_kzalloc(&pdev->dev, sizeof(*smem) + array_size, GFP_KERNEL);
@@ -666,39 +714,17 @@ static int qcom_smem_probe(struct platform_device *pdev)
666 smem->dev = &pdev->dev; 714 smem->dev = &pdev->dev;
667 smem->num_regions = num_regions; 715 smem->num_regions = num_regions;
668 716
669 np = of_parse_phandle(pdev->dev.of_node, "memory-region", 0); 717 ret = qcom_smem_map_memory(smem, &pdev->dev, "memory-region", 0);
670 if (!np) {
671 dev_err(&pdev->dev, "No memory-region specified\n");
672 return -EINVAL;
673 }
674
675 ret = of_address_to_resource(np, 0, &r);
676 of_node_put(np);
677 if (ret) 718 if (ret)
678 return ret; 719 return ret;
679 720
680 smem->regions[0].aux_base = (u32)r.start; 721 if (num_regions > 1 && (ret = qcom_smem_map_memory(smem, &pdev->dev,
681 smem->regions[0].size = resource_size(&r); 722 "qcom,rpm-msg-ram", 1)))
682 smem->regions[0].virt_base = devm_ioremap_nocache(&pdev->dev, 723 return ret;
683 r.start,
684 resource_size(&r));
685 if (!smem->regions[0].virt_base)
686 return -ENOMEM;
687
688 for (i = 1; i < num_regions; i++) {
689 res = platform_get_resource(pdev, IORESOURCE_MEM, i - 1);
690
691 smem->regions[i].aux_base = (u32)res->start;
692 smem->regions[i].size = resource_size(res);
693 smem->regions[i].virt_base = devm_ioremap_nocache(&pdev->dev,
694 res->start,
695 resource_size(res));
696 if (!smem->regions[i].virt_base)
697 return -ENOMEM;
698 }
699 724
700 header = smem->regions[0].virt_base; 725 header = smem->regions[0].virt_base;
701 if (header->initialized != 1 || header->reserved) { 726 if (le32_to_cpu(header->initialized) != 1 ||
727 le32_to_cpu(header->reserved)) {
702 dev_err(&pdev->dev, "SMEM is not initialized by SBL\n"); 728 dev_err(&pdev->dev, "SMEM is not initialized by SBL\n");
703 return -EINVAL; 729 return -EINVAL;
704 } 730 }
@@ -730,8 +756,8 @@ static int qcom_smem_probe(struct platform_device *pdev)
730 756
731static int qcom_smem_remove(struct platform_device *pdev) 757static int qcom_smem_remove(struct platform_device *pdev)
732{ 758{
733 __smem = NULL;
734 hwspin_lock_free(__smem->hwlock); 759 hwspin_lock_free(__smem->hwlock);
760 __smem = NULL;
735 761
736 return 0; 762 return 0;
737} 763}
diff --git a/drivers/soc/rockchip/Kconfig b/drivers/soc/rockchip/Kconfig
new file mode 100644
index 000000000000..7140ff825598
--- /dev/null
+++ b/drivers/soc/rockchip/Kconfig
@@ -0,0 +1,18 @@
1if ARCH_ROCKCHIP || COMPILE_TEST
2
3#
4# Rockchip Soc drivers
5#
6config ROCKCHIP_PM_DOMAINS
7 bool "Rockchip generic power domain"
8 depends on PM
9 select PM_GENERIC_DOMAINS
10 help
11 Say y here to enable power domain support.
12 In order to meet high performance and low power requirements, a power
13 management unit is designed or saving power when RK3288 in low power
14 mode. The RK3288 PMU is dedicated for managing the power of the whole chip.
15
16 If unsure, say N.
17
18endif
diff --git a/drivers/soc/rockchip/Makefile b/drivers/soc/rockchip/Makefile
new file mode 100644
index 000000000000..3d73d0672d22
--- /dev/null
+++ b/drivers/soc/rockchip/Makefile
@@ -0,0 +1,4 @@
1#
2# Rockchip Soc drivers
3#
4obj-$(CONFIG_ROCKCHIP_PM_DOMAINS) += pm_domains.o
diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c
new file mode 100644
index 000000000000..534c58937a56
--- /dev/null
+++ b/drivers/soc/rockchip/pm_domains.c
@@ -0,0 +1,490 @@
1/*
2 * Rockchip Generic power domain support.
3 *
4 * Copyright (c) 2015 ROCKCHIP, Co. Ltd.
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#include <linux/io.h>
12#include <linux/err.h>
13#include <linux/pm_clock.h>
14#include <linux/pm_domain.h>
15#include <linux/of_address.h>
16#include <linux/of_platform.h>
17#include <linux/clk.h>
18#include <linux/regmap.h>
19#include <linux/mfd/syscon.h>
20#include <dt-bindings/power/rk3288-power.h>
21
22struct rockchip_domain_info {
23 int pwr_mask;
24 int status_mask;
25 int req_mask;
26 int idle_mask;
27 int ack_mask;
28};
29
30struct rockchip_pmu_info {
31 u32 pwr_offset;
32 u32 status_offset;
33 u32 req_offset;
34 u32 idle_offset;
35 u32 ack_offset;
36
37 u32 core_pwrcnt_offset;
38 u32 gpu_pwrcnt_offset;
39
40 unsigned int core_power_transition_time;
41 unsigned int gpu_power_transition_time;
42
43 int num_domains;
44 const struct rockchip_domain_info *domain_info;
45};
46
47struct rockchip_pm_domain {
48 struct generic_pm_domain genpd;
49 const struct rockchip_domain_info *info;
50 struct rockchip_pmu *pmu;
51 int num_clks;
52 struct clk *clks[];
53};
54
55struct rockchip_pmu {
56 struct device *dev;
57 struct regmap *regmap;
58 const struct rockchip_pmu_info *info;
59 struct mutex mutex; /* mutex lock for pmu */
60 struct genpd_onecell_data genpd_data;
61 struct generic_pm_domain *domains[];
62};
63
64#define to_rockchip_pd(gpd) container_of(gpd, struct rockchip_pm_domain, genpd)
65
66#define DOMAIN(pwr, status, req, idle, ack) \
67{ \
68 .pwr_mask = BIT(pwr), \
69 .status_mask = BIT(status), \
70 .req_mask = BIT(req), \
71 .idle_mask = BIT(idle), \
72 .ack_mask = BIT(ack), \
73}
74
75#define DOMAIN_RK3288(pwr, status, req) \
76 DOMAIN(pwr, status, req, req, (req) + 16)
77
78static bool rockchip_pmu_domain_is_idle(struct rockchip_pm_domain *pd)
79{
80 struct rockchip_pmu *pmu = pd->pmu;
81 const struct rockchip_domain_info *pd_info = pd->info;
82 unsigned int val;
83
84 regmap_read(pmu->regmap, pmu->info->idle_offset, &val);
85 return (val & pd_info->idle_mask) == pd_info->idle_mask;
86}
87
88static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd,
89 bool idle)
90{
91 const struct rockchip_domain_info *pd_info = pd->info;
92 struct rockchip_pmu *pmu = pd->pmu;
93 unsigned int val;
94
95 regmap_update_bits(pmu->regmap, pmu->info->req_offset,
96 pd_info->req_mask, idle ? -1U : 0);
97
98 dsb(sy);
99
100 do {
101 regmap_read(pmu->regmap, pmu->info->ack_offset, &val);
102 } while ((val & pd_info->ack_mask) != (idle ? pd_info->ack_mask : 0));
103
104 while (rockchip_pmu_domain_is_idle(pd) != idle)
105 cpu_relax();
106
107 return 0;
108}
109
110static bool rockchip_pmu_domain_is_on(struct rockchip_pm_domain *pd)
111{
112 struct rockchip_pmu *pmu = pd->pmu;
113 unsigned int val;
114
115 regmap_read(pmu->regmap, pmu->info->status_offset, &val);
116
117 /* 1'b0: power on, 1'b1: power off */
118 return !(val & pd->info->status_mask);
119}
120
121static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
122 bool on)
123{
124 struct rockchip_pmu *pmu = pd->pmu;
125
126 regmap_update_bits(pmu->regmap, pmu->info->pwr_offset,
127 pd->info->pwr_mask, on ? 0 : -1U);
128
129 dsb(sy);
130
131 while (rockchip_pmu_domain_is_on(pd) != on)
132 cpu_relax();
133}
134
135static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on)
136{
137 int i;
138
139 mutex_lock(&pd->pmu->mutex);
140
141 if (rockchip_pmu_domain_is_on(pd) != power_on) {
142 for (i = 0; i < pd->num_clks; i++)
143 clk_enable(pd->clks[i]);
144
145 if (!power_on) {
146 /* FIXME: add code to save AXI_QOS */
147
148 /* if powering down, idle request to NIU first */
149 rockchip_pmu_set_idle_request(pd, true);
150 }
151
152 rockchip_do_pmu_set_power_domain(pd, power_on);
153
154 if (power_on) {
155 /* if powering up, leave idle mode */
156 rockchip_pmu_set_idle_request(pd, false);
157
158 /* FIXME: add code to restore AXI_QOS */
159 }
160
161 for (i = pd->num_clks - 1; i >= 0; i--)
162 clk_disable(pd->clks[i]);
163 }
164
165 mutex_unlock(&pd->pmu->mutex);
166 return 0;
167}
168
169static int rockchip_pd_power_on(struct generic_pm_domain *domain)
170{
171 struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
172
173 return rockchip_pd_power(pd, true);
174}
175
176static int rockchip_pd_power_off(struct generic_pm_domain *domain)
177{
178 struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
179
180 return rockchip_pd_power(pd, false);
181}
182
183static int rockchip_pd_attach_dev(struct generic_pm_domain *genpd,
184 struct device *dev)
185{
186 struct clk *clk;
187 int i;
188 int error;
189
190 dev_dbg(dev, "attaching to power domain '%s'\n", genpd->name);
191
192 error = pm_clk_create(dev);
193 if (error) {
194 dev_err(dev, "pm_clk_create failed %d\n", error);
195 return error;
196 }
197
198 i = 0;
199 while ((clk = of_clk_get(dev->of_node, i++)) && !IS_ERR(clk)) {
200 dev_dbg(dev, "adding clock '%pC' to list of PM clocks\n", clk);
201 error = pm_clk_add_clk(dev, clk);
202 if (error) {
203 dev_err(dev, "pm_clk_add_clk failed %d\n", error);
204 clk_put(clk);
205 pm_clk_destroy(dev);
206 return error;
207 }
208 }
209
210 return 0;
211}
212
213static void rockchip_pd_detach_dev(struct generic_pm_domain *genpd,
214 struct device *dev)
215{
216 dev_dbg(dev, "detaching from power domain '%s'\n", genpd->name);
217
218 pm_clk_destroy(dev);
219}
220
221static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
222 struct device_node *node)
223{
224 const struct rockchip_domain_info *pd_info;
225 struct rockchip_pm_domain *pd;
226 struct clk *clk;
227 int clk_cnt;
228 int i;
229 u32 id;
230 int error;
231
232 error = of_property_read_u32(node, "reg", &id);
233 if (error) {
234 dev_err(pmu->dev,
235 "%s: failed to retrieve domain id (reg): %d\n",
236 node->name, error);
237 return -EINVAL;
238 }
239
240 if (id >= pmu->info->num_domains) {
241 dev_err(pmu->dev, "%s: invalid domain id %d\n",
242 node->name, id);
243 return -EINVAL;
244 }
245
246 pd_info = &pmu->info->domain_info[id];
247 if (!pd_info) {
248 dev_err(pmu->dev, "%s: undefined domain id %d\n",
249 node->name, id);
250 return -EINVAL;
251 }
252
253 clk_cnt = of_count_phandle_with_args(node, "clocks", "#clock-cells");
254 pd = devm_kzalloc(pmu->dev,
255 sizeof(*pd) + clk_cnt * sizeof(pd->clks[0]),
256 GFP_KERNEL);
257 if (!pd)
258 return -ENOMEM;
259
260 pd->info = pd_info;
261 pd->pmu = pmu;
262
263 for (i = 0; i < clk_cnt; i++) {
264 clk = of_clk_get(node, i);
265 if (IS_ERR(clk)) {
266 error = PTR_ERR(clk);
267 dev_err(pmu->dev,
268 "%s: failed to get clk at index %d: %d\n",
269 node->name, i, error);
270 goto err_out;
271 }
272
273 error = clk_prepare(clk);
274 if (error) {
275 dev_err(pmu->dev,
276 "%s: failed to prepare clk %pC (index %d): %d\n",
277 node->name, clk, i, error);
278 clk_put(clk);
279 goto err_out;
280 }
281
282 pd->clks[pd->num_clks++] = clk;
283
284 dev_dbg(pmu->dev, "added clock '%pC' to domain '%s'\n",
285 clk, node->name);
286 }
287
288 error = rockchip_pd_power(pd, true);
289 if (error) {
290 dev_err(pmu->dev,
291 "failed to power on domain '%s': %d\n",
292 node->name, error);
293 goto err_out;
294 }
295
296 pd->genpd.name = node->name;
297 pd->genpd.power_off = rockchip_pd_power_off;
298 pd->genpd.power_on = rockchip_pd_power_on;
299 pd->genpd.attach_dev = rockchip_pd_attach_dev;
300 pd->genpd.detach_dev = rockchip_pd_detach_dev;
301 pd->genpd.flags = GENPD_FLAG_PM_CLK;
302 pm_genpd_init(&pd->genpd, NULL, false);
303
304 pmu->genpd_data.domains[id] = &pd->genpd;
305 return 0;
306
307err_out:
308 while (--i >= 0) {
309 clk_unprepare(pd->clks[i]);
310 clk_put(pd->clks[i]);
311 }
312 return error;
313}
314
315static void rockchip_pm_remove_one_domain(struct rockchip_pm_domain *pd)
316{
317 int i;
318
319 for (i = 0; i < pd->num_clks; i++) {
320 clk_unprepare(pd->clks[i]);
321 clk_put(pd->clks[i]);
322 }
323
324 /* protect the zeroing of pm->num_clks */
325 mutex_lock(&pd->pmu->mutex);
326 pd->num_clks = 0;
327 mutex_unlock(&pd->pmu->mutex);
328
329 /* devm will free our memory */
330}
331
332static void rockchip_pm_domain_cleanup(struct rockchip_pmu *pmu)
333{
334 struct generic_pm_domain *genpd;
335 struct rockchip_pm_domain *pd;
336 int i;
337
338 for (i = 0; i < pmu->genpd_data.num_domains; i++) {
339 genpd = pmu->genpd_data.domains[i];
340 if (genpd) {
341 pd = to_rockchip_pd(genpd);
342 rockchip_pm_remove_one_domain(pd);
343 }
344 }
345
346 /* devm will free our memory */
347}
348
349static void rockchip_configure_pd_cnt(struct rockchip_pmu *pmu,
350 u32 domain_reg_offset,
351 unsigned int count)
352{
353 /* First configure domain power down transition count ... */
354 regmap_write(pmu->regmap, domain_reg_offset, count);
355 /* ... and then power up count. */
356 regmap_write(pmu->regmap, domain_reg_offset + 4, count);
357}
358
359static int rockchip_pm_domain_probe(struct platform_device *pdev)
360{
361 struct device *dev = &pdev->dev;
362 struct device_node *np = dev->of_node;
363 struct device_node *node;
364 struct device *parent;
365 struct rockchip_pmu *pmu;
366 const struct of_device_id *match;
367 const struct rockchip_pmu_info *pmu_info;
368 int error;
369
370 if (!np) {
371 dev_err(dev, "device tree node not found\n");
372 return -ENODEV;
373 }
374
375 match = of_match_device(dev->driver->of_match_table, dev);
376 if (!match || !match->data) {
377 dev_err(dev, "missing pmu data\n");
378 return -EINVAL;
379 }
380
381 pmu_info = match->data;
382
383 pmu = devm_kzalloc(dev,
384 sizeof(*pmu) +
385 pmu_info->num_domains * sizeof(pmu->domains[0]),
386 GFP_KERNEL);
387 if (!pmu)
388 return -ENOMEM;
389
390 pmu->dev = &pdev->dev;
391 mutex_init(&pmu->mutex);
392
393 pmu->info = pmu_info;
394
395 pmu->genpd_data.domains = pmu->domains;
396 pmu->genpd_data.num_domains = pmu_info->num_domains;
397
398 parent = dev->parent;
399 if (!parent) {
400 dev_err(dev, "no parent for syscon devices\n");
401 return -ENODEV;
402 }
403
404 pmu->regmap = syscon_node_to_regmap(parent->of_node);
405
406 /*
407 * Configure power up and down transition delays for CORE
408 * and GPU domains.
409 */
410 rockchip_configure_pd_cnt(pmu, pmu_info->core_pwrcnt_offset,
411 pmu_info->core_power_transition_time);
412 rockchip_configure_pd_cnt(pmu, pmu_info->gpu_pwrcnt_offset,
413 pmu_info->gpu_power_transition_time);
414
415 error = -ENODEV;
416
417 for_each_available_child_of_node(np, node) {
418 error = rockchip_pm_add_one_domain(pmu, node);
419 if (error) {
420 dev_err(dev, "failed to handle node %s: %d\n",
421 node->name, error);
422 goto err_out;
423 }
424 }
425
426 if (error) {
427 dev_dbg(dev, "no power domains defined\n");
428 goto err_out;
429 }
430
431 of_genpd_add_provider_onecell(np, &pmu->genpd_data);
432
433 return 0;
434
435err_out:
436 rockchip_pm_domain_cleanup(pmu);
437 return error;
438}
439
440static const struct rockchip_domain_info rk3288_pm_domains[] = {
441 [RK3288_PD_VIO] = DOMAIN_RK3288(7, 7, 4),
442 [RK3288_PD_HEVC] = DOMAIN_RK3288(14, 10, 9),
443 [RK3288_PD_VIDEO] = DOMAIN_RK3288(8, 8, 3),
444 [RK3288_PD_GPU] = DOMAIN_RK3288(9, 9, 2),
445};
446
447static const struct rockchip_pmu_info rk3288_pmu = {
448 .pwr_offset = 0x08,
449 .status_offset = 0x0c,
450 .req_offset = 0x10,
451 .idle_offset = 0x14,
452 .ack_offset = 0x14,
453
454 .core_pwrcnt_offset = 0x34,
455 .gpu_pwrcnt_offset = 0x3c,
456
457 .core_power_transition_time = 24, /* 1us */
458 .gpu_power_transition_time = 24, /* 1us */
459
460 .num_domains = ARRAY_SIZE(rk3288_pm_domains),
461 .domain_info = rk3288_pm_domains,
462};
463
464static const struct of_device_id rockchip_pm_domain_dt_match[] = {
465 {
466 .compatible = "rockchip,rk3288-power-controller",
467 .data = (void *)&rk3288_pmu,
468 },
469 { /* sentinel */ },
470};
471
472static struct platform_driver rockchip_pm_domain_driver = {
473 .probe = rockchip_pm_domain_probe,
474 .driver = {
475 .name = "rockchip-pm-domain",
476 .of_match_table = rockchip_pm_domain_dt_match,
477 /*
478 * We can't forcibly eject devices form power domain,
479 * so we can't really remove power domains once they
480 * were added.
481 */
482 .suppress_bind_attrs = true,
483 },
484};
485
486static int __init rockchip_pm_domain_drv_register(void)
487{
488 return platform_driver_register(&rockchip_pm_domain_driver);
489}
490postcore_initcall(rockchip_pm_domain_drv_register);
diff --git a/include/dt-bindings/clock/berlin2q.h b/include/dt-bindings/clock/berlin2q.h
index 287fc3b4afb2..72eaf91c9ca6 100644
--- a/include/dt-bindings/clock/berlin2q.h
+++ b/include/dt-bindings/clock/berlin2q.h
@@ -29,3 +29,4 @@
29#define CLKID_SMEMC 24 29#define CLKID_SMEMC 24
30#define CLKID_PCIE 25 30#define CLKID_PCIE 25
31#define CLKID_TWD 26 31#define CLKID_TWD 26
32#define CLKID_CPU 27
diff --git a/include/dt-bindings/power/rk3288-power.h b/include/dt-bindings/power/rk3288-power.h
new file mode 100644
index 000000000000..b8b1045f3daa
--- /dev/null
+++ b/include/dt-bindings/power/rk3288-power.h
@@ -0,0 +1,31 @@
1#ifndef __DT_BINDINGS_POWER_RK3288_POWER_H__
2#define __DT_BINDINGS_POWER_RK3288_POWER_H__
3
4/**
5 * RK3288 Power Domain and Voltage Domain Summary.
6 */
7
8/* VD_CORE */
9#define RK3288_PD_A17_0 0
10#define RK3288_PD_A17_1 1
11#define RK3288_PD_A17_2 2
12#define RK3288_PD_A17_3 3
13#define RK3288_PD_SCU 4
14#define RK3288_PD_DEBUG 5
15#define RK3288_PD_MEM 6
16
17/* VD_LOGIC */
18#define RK3288_PD_BUS 7
19#define RK3288_PD_PERI 8
20#define RK3288_PD_VIO 9
21#define RK3288_PD_ALIVE 10
22#define RK3288_PD_HEVC 11
23#define RK3288_PD_VIDEO 12
24
25/* VD_GPU */
26#define RK3288_PD_GPU 13
27
28/* VD_PMU */
29#define RK3288_PD_PMU 14
30
31#endif
diff --git a/include/linux/atmel_tc.h b/include/linux/atmel_tc.h
index b87c1c7c242a..468fdfa643f0 100644
--- a/include/linux/atmel_tc.h
+++ b/include/linux/atmel_tc.h
@@ -67,6 +67,7 @@ struct atmel_tc {
67 const struct atmel_tcb_config *tcb_config; 67 const struct atmel_tcb_config *tcb_config;
68 int irq[3]; 68 int irq[3];
69 struct clk *clk[3]; 69 struct clk *clk[3];
70 struct clk *slow_clk;
70 struct list_head node; 71 struct list_head node;
71 bool allocated; 72 bool allocated;
72}; 73};
diff --git a/include/linux/psci.h b/include/linux/psci.h
index a682fcc91c33..12c4865457ad 100644
--- a/include/linux/psci.h
+++ b/include/linux/psci.h
@@ -21,6 +21,8 @@
21#define PSCI_POWER_STATE_TYPE_POWER_DOWN 1 21#define PSCI_POWER_STATE_TYPE_POWER_DOWN 1
22 22
23bool psci_tos_resident_on(int cpu); 23bool psci_tos_resident_on(int cpu);
24bool psci_power_state_loses_context(u32 state);
25bool psci_power_state_is_valid(u32 state);
24 26
25struct psci_operations { 27struct psci_operations {
26 int (*cpu_suspend)(u32 state, unsigned long entry_point); 28 int (*cpu_suspend)(u32 state, unsigned long entry_point);
diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h
index 6e7d5ec65838..9e12000914b3 100644
--- a/include/linux/qcom_scm.h
+++ b/include/linux/qcom_scm.h
@@ -23,6 +23,8 @@ struct qcom_scm_hdcp_req {
23 u32 val; 23 u32 val;
24}; 24};
25 25
26extern bool qcom_scm_is_available(void);
27
26extern bool qcom_scm_hdcp_available(void); 28extern bool qcom_scm_hdcp_available(void);
27extern int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, 29extern int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt,
28 u32 *resp); 30 u32 *resp);
diff --git a/include/linux/scpi_protocol.h b/include/linux/scpi_protocol.h
new file mode 100644
index 000000000000..80af3cd35ae4
--- /dev/null
+++ b/include/linux/scpi_protocol.h
@@ -0,0 +1,78 @@
1/*
2 * SCPI Message Protocol driver header
3 *
4 * Copyright (C) 2014 ARM Ltd.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18#include <linux/types.h>
19
20struct scpi_opp {
21 u32 freq;
22 u32 m_volt;
23} __packed;
24
25struct scpi_dvfs_info {
26 unsigned int count;
27 unsigned int latency; /* in nanoseconds */
28 struct scpi_opp *opps;
29};
30
31enum scpi_sensor_class {
32 TEMPERATURE,
33 VOLTAGE,
34 CURRENT,
35 POWER,
36};
37
38struct scpi_sensor_info {
39 u16 sensor_id;
40 u8 class;
41 u8 trigger_type;
42 char name[20];
43} __packed;
44
45/**
46 * struct scpi_ops - represents the various operations provided
47 * by SCP through SCPI message protocol
48 * @get_version: returns the major and minor revision on the SCPI
49 * message protocol
50 * @clk_get_range: gets clock range limit(min - max in Hz)
51 * @clk_get_val: gets clock value(in Hz)
52 * @clk_set_val: sets the clock value, setting to 0 will disable the
53 * clock (if supported)
54 * @dvfs_get_idx: gets the Operating Point of the given power domain.
55 * OPP is an index to the list return by @dvfs_get_info
56 * @dvfs_set_idx: sets the Operating Point of the given power domain.
57 * OPP is an index to the list return by @dvfs_get_info
58 * @dvfs_get_info: returns the DVFS capabilities of the given power
59 * domain. It includes the OPP list and the latency information
60 */
61struct scpi_ops {
62 u32 (*get_version)(void);
63 int (*clk_get_range)(u16, unsigned long *, unsigned long *);
64 unsigned long (*clk_get_val)(u16);
65 int (*clk_set_val)(u16, unsigned long);
66 int (*dvfs_get_idx)(u8);
67 int (*dvfs_set_idx)(u8, u8);
68 struct scpi_dvfs_info *(*dvfs_get_info)(u8);
69 int (*sensor_get_capability)(u16 *sensors);
70 int (*sensor_get_info)(u16 sensor_id, struct scpi_sensor_info *);
71 int (*sensor_get_value)(u16, u32 *);
72};
73
74#if IS_ENABLED(CONFIG_ARM_SCPI_PROTOCOL)
75struct scpi_ops *get_scpi_ops(void);
76#else
77static inline struct scpi_ops *get_scpi_ops(void) { return NULL; }
78#endif
diff --git a/include/linux/soc/qcom/smd.h b/include/linux/soc/qcom/smd.h
index d7e50aa6a4ac..d0cb6d189a0a 100644
--- a/include/linux/soc/qcom/smd.h
+++ b/include/linux/soc/qcom/smd.h
@@ -9,6 +9,14 @@ struct qcom_smd_channel;
9struct qcom_smd_lookup; 9struct qcom_smd_lookup;
10 10
11/** 11/**
12 * struct qcom_smd_id - struct used for matching a smd device
13 * @name: name of the channel
14 */
15struct qcom_smd_id {
16 char name[20];
17};
18
19/**
12 * struct qcom_smd_device - smd device struct 20 * struct qcom_smd_device - smd device struct
13 * @dev: the device struct 21 * @dev: the device struct
14 * @channel: handle to the smd channel for this device 22 * @channel: handle to the smd channel for this device
@@ -21,6 +29,7 @@ struct qcom_smd_device {
21/** 29/**
22 * struct qcom_smd_driver - smd driver struct 30 * struct qcom_smd_driver - smd driver struct
23 * @driver: underlying device driver 31 * @driver: underlying device driver
32 * @smd_match_table: static channel match table
24 * @probe: invoked when the smd channel is found 33 * @probe: invoked when the smd channel is found
25 * @remove: invoked when the smd channel is closed 34 * @remove: invoked when the smd channel is closed
26 * @callback: invoked when an inbound message is received on the channel, 35 * @callback: invoked when an inbound message is received on the channel,
@@ -29,6 +38,8 @@ struct qcom_smd_device {
29 */ 38 */
30struct qcom_smd_driver { 39struct qcom_smd_driver {
31 struct device_driver driver; 40 struct device_driver driver;
41 const struct qcom_smd_id *smd_match_table;
42
32 int (*probe)(struct qcom_smd_device *dev); 43 int (*probe)(struct qcom_smd_device *dev);
33 void (*remove)(struct qcom_smd_device *dev); 44 void (*remove)(struct qcom_smd_device *dev);
34 int (*callback)(struct qcom_smd_device *, const void *, size_t); 45 int (*callback)(struct qcom_smd_device *, const void *, size_t);
diff --git a/include/linux/soc/qcom/smem.h b/include/linux/soc/qcom/smem.h
index bc9630d3aced..785e196ee2ca 100644
--- a/include/linux/soc/qcom/smem.h
+++ b/include/linux/soc/qcom/smem.h
@@ -4,7 +4,7 @@
4#define QCOM_SMEM_HOST_ANY -1 4#define QCOM_SMEM_HOST_ANY -1
5 5
6int qcom_smem_alloc(unsigned host, unsigned item, size_t size); 6int qcom_smem_alloc(unsigned host, unsigned item, size_t size);
7int qcom_smem_get(unsigned host, unsigned item, void **ptr, size_t *size); 7void *qcom_smem_get(unsigned host, unsigned item, size_t *size);
8 8
9int qcom_smem_get_free_space(unsigned host); 9int qcom_smem_get_free_space(unsigned host);
10 10
diff --git a/include/linux/sunxi-rsb.h b/include/linux/sunxi-rsb.h
new file mode 100644
index 000000000000..7e75bb0346d0
--- /dev/null
+++ b/include/linux/sunxi-rsb.h
@@ -0,0 +1,105 @@
1/*
2 * Allwinner Reduced Serial Bus Driver
3 *
4 * Copyright (c) 2015 Chen-Yu Tsai
5 *
6 * Author: Chen-Yu Tsai <wens@csie.org>
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12#ifndef _SUNXI_RSB_H
13#define _SUNXI_RSB_H
14
15#include <linux/device.h>
16#include <linux/regmap.h>
17#include <linux/types.h>
18
19struct sunxi_rsb;
20
21/**
22 * struct sunxi_rsb_device - Basic representation of an RSB device
23 * @dev: Driver model representation of the device.
24 * @ctrl: RSB controller managing the bus hosting this device.
25 * @rtaddr: This device's runtime address
26 * @hwaddr: This device's hardware address
27 */
28struct sunxi_rsb_device {
29 struct device dev;
30 struct sunxi_rsb *rsb;
31 int irq;
32 u8 rtaddr;
33 u16 hwaddr;
34};
35
36static inline struct sunxi_rsb_device *to_sunxi_rsb_device(struct device *d)
37{
38 return container_of(d, struct sunxi_rsb_device, dev);
39}
40
41static inline void *sunxi_rsb_device_get_drvdata(const struct sunxi_rsb_device *rdev)
42{
43 return dev_get_drvdata(&rdev->dev);
44}
45
46static inline void sunxi_rsb_device_set_drvdata(struct sunxi_rsb_device *rdev,
47 void *data)
48{
49 dev_set_drvdata(&rdev->dev, data);
50}
51
52/**
53 * struct sunxi_rsb_driver - RSB slave device driver
54 * @driver: RSB device drivers should initialize name and owner field of
55 * this structure.
56 * @probe: binds this driver to a RSB device.
57 * @remove: unbinds this driver from the RSB device.
58 */
59struct sunxi_rsb_driver {
60 struct device_driver driver;
61 int (*probe)(struct sunxi_rsb_device *rdev);
62 int (*remove)(struct sunxi_rsb_device *rdev);
63};
64
65static inline struct sunxi_rsb_driver *to_sunxi_rsb_driver(struct device_driver *d)
66{
67 return container_of(d, struct sunxi_rsb_driver, driver);
68}
69
70int sunxi_rsb_driver_register(struct sunxi_rsb_driver *rdrv);
71
72/**
73 * sunxi_rsb_driver_unregister() - unregister an RSB client driver
74 * @rdrv: the driver to unregister
75 */
76static inline void sunxi_rsb_driver_unregister(struct sunxi_rsb_driver *rdrv)
77{
78 if (rdrv)
79 driver_unregister(&rdrv->driver);
80}
81
82#define module_sunxi_rsb_driver(__sunxi_rsb_driver) \
83 module_driver(__sunxi_rsb_driver, sunxi_rsb_driver_register, \
84 sunxi_rsb_driver_unregister)
85
86struct regmap *__devm_regmap_init_sunxi_rsb(struct sunxi_rsb_device *rdev,
87 const struct regmap_config *config,
88 struct lock_class_key *lock_key,
89 const char *lock_name);
90
91/**
92 * devm_regmap_init_sunxi_rsb(): Initialise managed register map
93 *
94 * @rdev: Device that will be interacted with
95 * @config: Configuration for register map
96 *
97 * The return value will be an ERR_PTR() on error or a valid pointer
98 * to a struct regmap. The regmap will be automatically freed by the
99 * device management code.
100 */
101#define devm_regmap_init_sunxi_rsb(rdev, config) \
102 __regmap_lockdep_wrapper(__devm_regmap_init_sunxi_rsb, #config, \
103 rdev, config)
104
105#endif /* _SUNXI_RSB_H */
diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h
new file mode 100644
index 000000000000..c07d74aa39bf
--- /dev/null
+++ b/include/soc/bcm2835/raspberrypi-firmware.h
@@ -0,0 +1,120 @@
1/*
2 * Copyright © 2015 Broadcom
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#ifndef __SOC_RASPBERRY_FIRMWARE_H__
10#define __SOC_RASPBERRY_FIRMWARE_H__
11
12#include <linux/types.h>
13#include <linux/of_device.h>
14
15struct rpi_firmware;
16
17enum rpi_firmware_property_status {
18 RPI_FIRMWARE_STATUS_REQUEST = 0,
19 RPI_FIRMWARE_STATUS_SUCCESS = 0x80000000,
20 RPI_FIRMWARE_STATUS_ERROR = 0x80000001,
21};
22
23/**
24 * struct rpi_firmware_property_tag_header - Firmware property tag header
25 * @tag: One of enum_mbox_property_tag.
26 * @buf_size: The number of bytes in the value buffer following this
27 * struct.
28 * @req_resp_size: On submit, the length of the request (though it doesn't
29 * appear to be currently used by the firmware). On return,
30 * the length of the response (always 4 byte aligned), with
31 * the low bit set.
32 */
33struct rpi_firmware_property_tag_header {
34 u32 tag;
35 u32 buf_size;
36 u32 req_resp_size;
37};
38
39enum rpi_firmware_property_tag {
40 RPI_FIRMWARE_PROPERTY_END = 0,
41 RPI_FIRMWARE_GET_FIRMWARE_REVISION = 0x00000001,
42
43 RPI_FIRMWARE_SET_CURSOR_INFO = 0x00008010,
44 RPI_FIRMWARE_SET_CURSOR_STATE = 0x00008011,
45
46 RPI_FIRMWARE_GET_BOARD_MODEL = 0x00010001,
47 RPI_FIRMWARE_GET_BOARD_REVISION = 0x00010002,
48 RPI_FIRMWARE_GET_BOARD_MAC_ADDRESS = 0x00010003,
49 RPI_FIRMWARE_GET_BOARD_SERIAL = 0x00010004,
50 RPI_FIRMWARE_GET_ARM_MEMORY = 0x00010005,
51 RPI_FIRMWARE_GET_VC_MEMORY = 0x00010006,
52 RPI_FIRMWARE_GET_CLOCKS = 0x00010007,
53 RPI_FIRMWARE_GET_POWER_STATE = 0x00020001,
54 RPI_FIRMWARE_GET_TIMING = 0x00020002,
55 RPI_FIRMWARE_SET_POWER_STATE = 0x00028001,
56 RPI_FIRMWARE_GET_CLOCK_STATE = 0x00030001,
57 RPI_FIRMWARE_GET_CLOCK_RATE = 0x00030002,
58 RPI_FIRMWARE_GET_VOLTAGE = 0x00030003,
59 RPI_FIRMWARE_GET_MAX_CLOCK_RATE = 0x00030004,
60 RPI_FIRMWARE_GET_MAX_VOLTAGE = 0x00030005,
61 RPI_FIRMWARE_GET_TEMPERATURE = 0x00030006,
62 RPI_FIRMWARE_GET_MIN_CLOCK_RATE = 0x00030007,
63 RPI_FIRMWARE_GET_MIN_VOLTAGE = 0x00030008,
64 RPI_FIRMWARE_GET_TURBO = 0x00030009,
65 RPI_FIRMWARE_GET_MAX_TEMPERATURE = 0x0003000a,
66 RPI_FIRMWARE_ALLOCATE_MEMORY = 0x0003000c,
67 RPI_FIRMWARE_LOCK_MEMORY = 0x0003000d,
68 RPI_FIRMWARE_UNLOCK_MEMORY = 0x0003000e,
69 RPI_FIRMWARE_RELEASE_MEMORY = 0x0003000f,
70 RPI_FIRMWARE_EXECUTE_CODE = 0x00030010,
71 RPI_FIRMWARE_EXECUTE_QPU = 0x00030011,
72 RPI_FIRMWARE_SET_ENABLE_QPU = 0x00030012,
73 RPI_FIRMWARE_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014,
74 RPI_FIRMWARE_GET_EDID_BLOCK = 0x00030020,
75 RPI_FIRMWARE_SET_CLOCK_STATE = 0x00038001,
76 RPI_FIRMWARE_SET_CLOCK_RATE = 0x00038002,
77 RPI_FIRMWARE_SET_VOLTAGE = 0x00038003,
78 RPI_FIRMWARE_SET_TURBO = 0x00038009,
79
80 /* Dispmanx TAGS */
81 RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE = 0x00040001,
82 RPI_FIRMWARE_FRAMEBUFFER_BLANK = 0x00040002,
83 RPI_FIRMWARE_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003,
84 RPI_FIRMWARE_FRAMEBUFFER_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004,
85 RPI_FIRMWARE_FRAMEBUFFER_GET_DEPTH = 0x00040005,
86 RPI_FIRMWARE_FRAMEBUFFER_GET_PIXEL_ORDER = 0x00040006,
87 RPI_FIRMWARE_FRAMEBUFFER_GET_ALPHA_MODE = 0x00040007,
88 RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH = 0x00040008,
89 RPI_FIRMWARE_FRAMEBUFFER_GET_VIRTUAL_OFFSET = 0x00040009,
90 RPI_FIRMWARE_FRAMEBUFFER_GET_OVERSCAN = 0x0004000a,
91 RPI_FIRMWARE_FRAMEBUFFER_GET_PALETTE = 0x0004000b,
92 RPI_FIRMWARE_FRAMEBUFFER_RELEASE = 0x00048001,
93 RPI_FIRMWARE_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003,
94 RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT = 0x00044004,
95 RPI_FIRMWARE_FRAMEBUFFER_TEST_DEPTH = 0x00044005,
96 RPI_FIRMWARE_FRAMEBUFFER_TEST_PIXEL_ORDER = 0x00044006,
97 RPI_FIRMWARE_FRAMEBUFFER_TEST_ALPHA_MODE = 0x00044007,
98 RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_OFFSET = 0x00044009,
99 RPI_FIRMWARE_FRAMEBUFFER_TEST_OVERSCAN = 0x0004400a,
100 RPI_FIRMWARE_FRAMEBUFFER_TEST_PALETTE = 0x0004400b,
101 RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003,
102 RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004,
103 RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH = 0x00048005,
104 RPI_FIRMWARE_FRAMEBUFFER_SET_PIXEL_ORDER = 0x00048006,
105 RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE = 0x00048007,
106 RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009,
107 RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a,
108 RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE = 0x0004800b,
109
110 RPI_FIRMWARE_GET_COMMAND_LINE = 0x00050001,
111 RPI_FIRMWARE_GET_DMA_CHANNELS = 0x00060001,
112};
113
114int rpi_firmware_property(struct rpi_firmware *fw,
115 u32 tag, void *data, size_t len);
116int rpi_firmware_property_list(struct rpi_firmware *fw,
117 void *data, size_t tag_size);
118struct rpi_firmware *rpi_firmware_get(struct device_node *firmware_node);
119
120#endif /* __SOC_RASPBERRY_FIRMWARE_H__ */
diff --git a/include/uapi/linux/psci.h b/include/uapi/linux/psci.h
index 310d83e0a91b..3d7a0fc021a7 100644
--- a/include/uapi/linux/psci.h
+++ b/include/uapi/linux/psci.h
@@ -46,6 +46,11 @@
46#define PSCI_0_2_FN64_MIGRATE PSCI_0_2_FN64(5) 46#define PSCI_0_2_FN64_MIGRATE PSCI_0_2_FN64(5)
47#define PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU PSCI_0_2_FN64(7) 47#define PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU PSCI_0_2_FN64(7)
48 48
49#define PSCI_1_0_FN_PSCI_FEATURES PSCI_0_2_FN(10)
50#define PSCI_1_0_FN_SYSTEM_SUSPEND PSCI_0_2_FN(14)
51
52#define PSCI_1_0_FN64_SYSTEM_SUSPEND PSCI_0_2_FN64(14)
53
49/* PSCI v0.2 power state encoding for CPU_SUSPEND function */ 54/* PSCI v0.2 power state encoding for CPU_SUSPEND function */
50#define PSCI_0_2_POWER_STATE_ID_MASK 0xffff 55#define PSCI_0_2_POWER_STATE_ID_MASK 0xffff
51#define PSCI_0_2_POWER_STATE_ID_SHIFT 0 56#define PSCI_0_2_POWER_STATE_ID_SHIFT 0
@@ -56,6 +61,13 @@
56#define PSCI_0_2_POWER_STATE_AFFL_MASK \ 61#define PSCI_0_2_POWER_STATE_AFFL_MASK \
57 (0x3 << PSCI_0_2_POWER_STATE_AFFL_SHIFT) 62 (0x3 << PSCI_0_2_POWER_STATE_AFFL_SHIFT)
58 63
64/* PSCI extended power state encoding for CPU_SUSPEND function */
65#define PSCI_1_0_EXT_POWER_STATE_ID_MASK 0xfffffff
66#define PSCI_1_0_EXT_POWER_STATE_ID_SHIFT 0
67#define PSCI_1_0_EXT_POWER_STATE_TYPE_SHIFT 30
68#define PSCI_1_0_EXT_POWER_STATE_TYPE_MASK \
69 (0x1 << PSCI_1_0_EXT_POWER_STATE_TYPE_SHIFT)
70
59/* PSCI v0.2 affinity level state returned by AFFINITY_INFO */ 71/* PSCI v0.2 affinity level state returned by AFFINITY_INFO */
60#define PSCI_0_2_AFFINITY_LEVEL_ON 0 72#define PSCI_0_2_AFFINITY_LEVEL_ON 0
61#define PSCI_0_2_AFFINITY_LEVEL_OFF 1 73#define PSCI_0_2_AFFINITY_LEVEL_OFF 1
@@ -76,6 +88,11 @@
76#define PSCI_VERSION_MINOR(ver) \ 88#define PSCI_VERSION_MINOR(ver) \
77 ((ver) & PSCI_VERSION_MINOR_MASK) 89 ((ver) & PSCI_VERSION_MINOR_MASK)
78 90
91/* PSCI features decoding (>=1.0) */
92#define PSCI_1_0_FEATURES_CPU_SUSPEND_PF_SHIFT 1
93#define PSCI_1_0_FEATURES_CPU_SUSPEND_PF_MASK \
94 (0x1 << PSCI_1_0_FEATURES_CPU_SUSPEND_PF_SHIFT)
95
79/* PSCI return values (inclusive of all PSCI versions) */ 96/* PSCI return values (inclusive of all PSCI versions) */
80#define PSCI_RET_SUCCESS 0 97#define PSCI_RET_SUCCESS 0
81#define PSCI_RET_NOT_SUPPORTED -1 98#define PSCI_RET_NOT_SUPPORTED -1
@@ -86,5 +103,6 @@
86#define PSCI_RET_INTERNAL_FAILURE -6 103#define PSCI_RET_INTERNAL_FAILURE -6
87#define PSCI_RET_NOT_PRESENT -7 104#define PSCI_RET_NOT_PRESENT -7
88#define PSCI_RET_DISABLED -8 105#define PSCI_RET_DISABLED -8
106#define PSCI_RET_INVALID_ADDRESS -9
89 107
90#endif /* _UAPI_LINUX_PSCI_H */ 108#endif /* _UAPI_LINUX_PSCI_H */