aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware
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 /drivers/firmware
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 ...
Diffstat (limited to 'drivers/firmware')
-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
6 files changed, 1161 insertions, 14 deletions
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");