aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNishanth Menon <nm@ti.com>2016-10-18 19:08:34 -0400
committerTero Kristo <t-kristo@ti.com>2016-10-27 05:09:11 -0400
commitaa276781a64a5f15ecc21e920960c5b1f84e5fee (patch)
treedb4e9777479ce100f71007bd8760b77b79de6db0
parent04f1024e1df5eae18e36ce41bed3ddfec7f2477d (diff)
firmware: Add basic support for TI System Control Interface (TI-SCI) protocol
Texas Instrument's System Control Interface (TI-SCI) Message Protocol is used in Texas Instrument's System on Chip (SoC) such as those in keystone family K2G SoC to communicate between various compute processors with a central system controller entity. TI-SCI message protocol provides support for management of various hardware entities within the SoC. Add support driver to allow communication with system controller entity within the SoC using the mailbox client. We introduce the basic registration and query capability for the driver protocol as part of this change. Subsequent patches add in functionality specific to the TI-SCI features. Signed-off-by: Nishanth Menon <nm@ti.com> Signed-off-by: Tero Kristo <t-kristo@ti.com>
-rw-r--r--MAINTAINERS2
-rw-r--r--drivers/firmware/Kconfig15
-rw-r--r--drivers/firmware/Makefile1
-rw-r--r--drivers/firmware/ti_sci.c790
-rw-r--r--drivers/firmware/ti_sci.h93
-rw-r--r--include/linux/soc/ti/ti_sci_protocol.h69
6 files changed, 970 insertions, 0 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 2bafadf5747a..467b29fafaca 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11890,6 +11890,8 @@ M: Santosh Shilimkar <ssantosh@kernel.org>
11890L: linux-arm-kernel@lists.infradead.org 11890L: linux-arm-kernel@lists.infradead.org
11891S: Maintained 11891S: Maintained
11892F: Documentation/devicetree/bindings/arm/keystone/ti,sci.txt 11892F: Documentation/devicetree/bindings/arm/keystone/ti,sci.txt
11893F: drivers/firmware/ti_sci*
11894F: include/linux/soc/ti/ti_sci_protocol.h
11893 11895
11894THANKO'S RAREMONO AM/FM/SW RADIO RECEIVER USB DRIVER 11896THANKO'S RAREMONO AM/FM/SW RADIO RECEIVER USB DRIVER
11895M: Hans Verkuil <hverkuil@xs4all.nl> 11897M: Hans Verkuil <hverkuil@xs4all.nl>
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index bca172d42c74..9418d7d1b0a5 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -203,6 +203,21 @@ config QCOM_SCM_64
203 def_bool y 203 def_bool y
204 depends on QCOM_SCM && ARM64 204 depends on QCOM_SCM && ARM64
205 205
206config TI_SCI_PROTOCOL
207 tristate "TI System Control Interface (TISCI) Message Protocol"
208 depends on TI_MESSAGE_MANAGER
209 help
210 TI System Control Interface (TISCI) Message Protocol is used to manage
211 compute systems such as ARM, DSP etc with the system controller in
212 complex System on Chip(SoC) such as those found on certain keystone
213 generation SoC from TI.
214
215 System controller provides various facilities including power
216 management function support.
217
218 This protocol library is used by client drivers to use the features
219 provided by the system controller.
220
206config HAVE_ARM_SMCCC 221config HAVE_ARM_SMCCC
207 bool 222 bool
208 223
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 898ac41fa8b3..dcb52c423151 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_QCOM_SCM) += qcom_scm.o
20obj-$(CONFIG_QCOM_SCM_64) += qcom_scm-64.o 20obj-$(CONFIG_QCOM_SCM_64) += qcom_scm-64.o
21obj-$(CONFIG_QCOM_SCM_32) += qcom_scm-32.o 21obj-$(CONFIG_QCOM_SCM_32) += qcom_scm-32.o
22CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch armv7-a\n.arch_extension sec,-DREQUIRES_SEC=1) -march=armv7-a 22CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch armv7-a\n.arch_extension sec,-DREQUIRES_SEC=1) -march=armv7-a
23obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o
23 24
24obj-y += broadcom/ 25obj-y += broadcom/
25obj-y += meson/ 26obj-y += meson/
diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
new file mode 100644
index 000000000000..5e99d7c18276
--- /dev/null
+++ b/drivers/firmware/ti_sci.c
@@ -0,0 +1,790 @@
1/*
2 * Texas Instruments System Control Interface Protocol Driver
3 *
4 * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
5 * Nishanth Menon
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#define pr_fmt(fmt) "%s: " fmt, __func__
18
19#include <linux/bitmap.h>
20#include <linux/debugfs.h>
21#include <linux/export.h>
22#include <linux/io.h>
23#include <linux/kernel.h>
24#include <linux/mailbox_client.h>
25#include <linux/module.h>
26#include <linux/of_device.h>
27#include <linux/semaphore.h>
28#include <linux/slab.h>
29#include <linux/soc/ti/ti-msgmgr.h>
30#include <linux/soc/ti/ti_sci_protocol.h>
31
32#include "ti_sci.h"
33
34/* List of all TI SCI devices active in system */
35static LIST_HEAD(ti_sci_list);
36/* Protection for the entire list */
37static DEFINE_MUTEX(ti_sci_list_mutex);
38
39/**
40 * struct ti_sci_xfer - Structure representing a message flow
41 * @tx_message: Transmit message
42 * @rx_len: Receive message length
43 * @xfer_buf: Preallocated buffer to store receive message
44 * Since we work with request-ACK protocol, we can
45 * reuse the same buffer for the rx path as we
46 * use for the tx path.
47 * @done: completion event
48 */
49struct ti_sci_xfer {
50 struct ti_msgmgr_message tx_message;
51 u8 rx_len;
52 u8 *xfer_buf;
53 struct completion done;
54};
55
56/**
57 * struct ti_sci_xfers_info - Structure to manage transfer information
58 * @sem_xfer_count: Counting Semaphore for managing max simultaneous
59 * Messages.
60 * @xfer_block: Preallocated Message array
61 * @xfer_alloc_table: Bitmap table for allocated messages.
62 * Index of this bitmap table is also used for message
63 * sequence identifier.
64 * @xfer_lock: Protection for message allocation
65 */
66struct ti_sci_xfers_info {
67 struct semaphore sem_xfer_count;
68 struct ti_sci_xfer *xfer_block;
69 unsigned long *xfer_alloc_table;
70 /* protect transfer allocation */
71 spinlock_t xfer_lock;
72};
73
74/**
75 * struct ti_sci_desc - Description of SoC integration
76 * @host_id: Host identifier representing the compute entity
77 * @max_rx_timeout_ms: Timeout for communication with SoC (in Milliseconds)
78 * @max_msgs: Maximum number of messages that can be pending
79 * simultaneously in the system
80 * @max_msg_size: Maximum size of data per message that can be handled.
81 */
82struct ti_sci_desc {
83 u8 host_id;
84 int max_rx_timeout_ms;
85 int max_msgs;
86 int max_msg_size;
87};
88
89/**
90 * struct ti_sci_info - Structure representing a TI SCI instance
91 * @dev: Device pointer
92 * @desc: SoC description for this instance
93 * @d: Debugfs file entry
94 * @debug_region: Memory region where the debug message are available
95 * @debug_region_size: Debug region size
96 * @debug_buffer: Buffer allocated to copy debug messages.
97 * @handle: Instance of TI SCI handle to send to clients.
98 * @cl: Mailbox Client
99 * @chan_tx: Transmit mailbox channel
100 * @chan_rx: Receive mailbox channel
101 * @minfo: Message info
102 * @node: list head
103 * @users: Number of users of this instance
104 */
105struct ti_sci_info {
106 struct device *dev;
107 const struct ti_sci_desc *desc;
108 struct dentry *d;
109 void __iomem *debug_region;
110 char *debug_buffer;
111 size_t debug_region_size;
112 struct ti_sci_handle handle;
113 struct mbox_client cl;
114 struct mbox_chan *chan_tx;
115 struct mbox_chan *chan_rx;
116 struct ti_sci_xfers_info minfo;
117 struct list_head node;
118 /* protected by ti_sci_list_mutex */
119 int users;
120};
121
122#define cl_to_ti_sci_info(c) container_of(c, struct ti_sci_info, cl)
123#define handle_to_ti_sci_info(h) container_of(h, struct ti_sci_info, handle)
124
125#ifdef CONFIG_DEBUG_FS
126
127/**
128 * ti_sci_debug_show() - Helper to dump the debug log
129 * @s: sequence file pointer
130 * @unused: unused.
131 *
132 * Return: 0
133 */
134static int ti_sci_debug_show(struct seq_file *s, void *unused)
135{
136 struct ti_sci_info *info = s->private;
137
138 memcpy_fromio(info->debug_buffer, info->debug_region,
139 info->debug_region_size);
140 /*
141 * We don't trust firmware to leave NULL terminated last byte (hence
142 * we have allocated 1 extra 0 byte). Since we cannot guarantee any
143 * specific data format for debug messages, We just present the data
144 * in the buffer as is - we expect the messages to be self explanatory.
145 */
146 seq_puts(s, info->debug_buffer);
147 return 0;
148}
149
150/**
151 * ti_sci_debug_open() - debug file open
152 * @inode: inode pointer
153 * @file: file pointer
154 *
155 * Return: result of single_open
156 */
157static int ti_sci_debug_open(struct inode *inode, struct file *file)
158{
159 return single_open(file, ti_sci_debug_show, inode->i_private);
160}
161
162/* log file operations */
163static const struct file_operations ti_sci_debug_fops = {
164 .open = ti_sci_debug_open,
165 .read = seq_read,
166 .llseek = seq_lseek,
167 .release = single_release,
168};
169
170/**
171 * ti_sci_debugfs_create() - Create log debug file
172 * @pdev: platform device pointer
173 * @info: Pointer to SCI entity information
174 *
175 * Return: 0 if all went fine, else corresponding error.
176 */
177static int ti_sci_debugfs_create(struct platform_device *pdev,
178 struct ti_sci_info *info)
179{
180 struct device *dev = &pdev->dev;
181 struct resource *res;
182 char debug_name[50] = "ti_sci_debug@";
183
184 /* Debug region is optional */
185 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
186 "debug_messages");
187 info->debug_region = devm_ioremap_resource(dev, res);
188 if (IS_ERR(info->debug_region))
189 return 0;
190 info->debug_region_size = resource_size(res);
191
192 info->debug_buffer = devm_kcalloc(dev, info->debug_region_size + 1,
193 sizeof(char), GFP_KERNEL);
194 if (!info->debug_buffer)
195 return -ENOMEM;
196 /* Setup NULL termination */
197 info->debug_buffer[info->debug_region_size] = 0;
198
199 info->d = debugfs_create_file(strncat(debug_name, dev_name(dev),
200 sizeof(debug_name)),
201 0444, NULL, info, &ti_sci_debug_fops);
202 if (IS_ERR(info->d))
203 return PTR_ERR(info->d);
204
205 dev_dbg(dev, "Debug region => %p, size = %zu bytes, resource: %pr\n",
206 info->debug_region, info->debug_region_size, res);
207 return 0;
208}
209
210/**
211 * ti_sci_debugfs_destroy() - clean up log debug file
212 * @pdev: platform device pointer
213 * @info: Pointer to SCI entity information
214 */
215static void ti_sci_debugfs_destroy(struct platform_device *pdev,
216 struct ti_sci_info *info)
217{
218 if (IS_ERR(info->debug_region))
219 return;
220
221 debugfs_remove(info->d);
222}
223#else /* CONFIG_DEBUG_FS */
224static inline int ti_sci_debugfs_create(struct platform_device *dev,
225 struct ti_sci_info *info)
226{
227 return 0;
228}
229
230static inline void ti_sci_debugfs_destroy(struct platform_device *dev,
231 struct ti_sci_info *info)
232{
233}
234#endif /* CONFIG_DEBUG_FS */
235
236/**
237 * ti_sci_dump_header_dbg() - Helper to dump a message header.
238 * @dev: Device pointer corresponding to the SCI entity
239 * @hdr: pointer to header.
240 */
241static inline void ti_sci_dump_header_dbg(struct device *dev,
242 struct ti_sci_msg_hdr *hdr)
243{
244 dev_dbg(dev, "MSGHDR:type=0x%04x host=0x%02x seq=0x%02x flags=0x%08x\n",
245 hdr->type, hdr->host, hdr->seq, hdr->flags);
246}
247
248/**
249 * ti_sci_rx_callback() - mailbox client callback for receive messages
250 * @cl: client pointer
251 * @m: mailbox message
252 *
253 * Processes one received message to appropriate transfer information and
254 * signals completion of the transfer.
255 *
256 * NOTE: This function will be invoked in IRQ context, hence should be
257 * as optimal as possible.
258 */
259static void ti_sci_rx_callback(struct mbox_client *cl, void *m)
260{
261 struct ti_sci_info *info = cl_to_ti_sci_info(cl);
262 struct device *dev = info->dev;
263 struct ti_sci_xfers_info *minfo = &info->minfo;
264 struct ti_msgmgr_message *mbox_msg = m;
265 struct ti_sci_msg_hdr *hdr = (struct ti_sci_msg_hdr *)mbox_msg->buf;
266 struct ti_sci_xfer *xfer;
267 u8 xfer_id;
268
269 xfer_id = hdr->seq;
270
271 /*
272 * Are we even expecting this?
273 * NOTE: barriers were implicit in locks used for modifying the bitmap
274 */
275 if (!test_bit(xfer_id, minfo->xfer_alloc_table)) {
276 dev_err(dev, "Message for %d is not expected!\n", xfer_id);
277 return;
278 }
279
280 xfer = &minfo->xfer_block[xfer_id];
281
282 /* Is the message of valid length? */
283 if (mbox_msg->len > info->desc->max_msg_size) {
284 dev_err(dev, "Unable to handle %d xfer(max %d)\n",
285 mbox_msg->len, info->desc->max_msg_size);
286 ti_sci_dump_header_dbg(dev, hdr);
287 return;
288 }
289 if (mbox_msg->len < xfer->rx_len) {
290 dev_err(dev, "Recv xfer %d < expected %d length\n",
291 mbox_msg->len, xfer->rx_len);
292 ti_sci_dump_header_dbg(dev, hdr);
293 return;
294 }
295
296 ti_sci_dump_header_dbg(dev, hdr);
297 /* Take a copy to the rx buffer.. */
298 memcpy(xfer->xfer_buf, mbox_msg->buf, xfer->rx_len);
299 complete(&xfer->done);
300}
301
302/**
303 * ti_sci_get_one_xfer() - Allocate one message
304 * @info: Pointer to SCI entity information
305 * @msg_type: Message type
306 * @msg_flags: Flag to set for the message
307 * @tx_message_size: transmit message size
308 * @rx_message_size: receive message size
309 *
310 * Helper function which is used by various command functions that are
311 * exposed to clients of this driver for allocating a message traffic event.
312 *
313 * This function can sleep depending on pending requests already in the system
314 * for the SCI entity. Further, this also holds a spinlock to maintain integrity
315 * of internal data structures.
316 *
317 * Return: 0 if all went fine, else corresponding error.
318 */
319static struct ti_sci_xfer *ti_sci_get_one_xfer(struct ti_sci_info *info,
320 u16 msg_type, u32 msg_flags,
321 size_t tx_message_size,
322 size_t rx_message_size)
323{
324 struct ti_sci_xfers_info *minfo = &info->minfo;
325 struct ti_sci_xfer *xfer;
326 struct ti_sci_msg_hdr *hdr;
327 unsigned long flags;
328 unsigned long bit_pos;
329 u8 xfer_id;
330 int ret;
331 int timeout;
332
333 /* Ensure we have sane transfer sizes */
334 if (rx_message_size > info->desc->max_msg_size ||
335 tx_message_size > info->desc->max_msg_size ||
336 rx_message_size < sizeof(*hdr) || tx_message_size < sizeof(*hdr))
337 return ERR_PTR(-ERANGE);
338
339 /*
340 * Ensure we have only controlled number of pending messages.
341 * Ideally, we might just have to wait a single message, be
342 * conservative and wait 5 times that..
343 */
344 timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms) * 5;
345 ret = down_timeout(&minfo->sem_xfer_count, timeout);
346 if (ret < 0)
347 return ERR_PTR(ret);
348
349 /* Keep the locked section as small as possible */
350 spin_lock_irqsave(&minfo->xfer_lock, flags);
351 bit_pos = find_first_zero_bit(minfo->xfer_alloc_table,
352 info->desc->max_msgs);
353 set_bit(bit_pos, minfo->xfer_alloc_table);
354 spin_unlock_irqrestore(&minfo->xfer_lock, flags);
355
356 /*
357 * We already ensured in probe that we can have max messages that can
358 * fit in hdr.seq - NOTE: this improves access latencies
359 * to predictable O(1) access, BUT, it opens us to risk if
360 * remote misbehaves with corrupted message sequence responses.
361 * If that happens, we are going to be messed up anyways..
362 */
363 xfer_id = (u8)bit_pos;
364
365 xfer = &minfo->xfer_block[xfer_id];
366
367 hdr = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
368 xfer->tx_message.len = tx_message_size;
369 xfer->rx_len = (u8)rx_message_size;
370
371 reinit_completion(&xfer->done);
372
373 hdr->seq = xfer_id;
374 hdr->type = msg_type;
375 hdr->host = info->desc->host_id;
376 hdr->flags = msg_flags;
377
378 return xfer;
379}
380
381/**
382 * ti_sci_put_one_xfer() - Release a message
383 * @minfo: transfer info pointer
384 * @xfer: message that was reserved by ti_sci_get_one_xfer
385 *
386 * This holds a spinlock to maintain integrity of internal data structures.
387 */
388static void ti_sci_put_one_xfer(struct ti_sci_xfers_info *minfo,
389 struct ti_sci_xfer *xfer)
390{
391 unsigned long flags;
392 struct ti_sci_msg_hdr *hdr;
393 u8 xfer_id;
394
395 hdr = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
396 xfer_id = hdr->seq;
397
398 /*
399 * Keep the locked section as small as possible
400 * NOTE: we might escape with smp_mb and no lock here..
401 * but just be conservative and symmetric.
402 */
403 spin_lock_irqsave(&minfo->xfer_lock, flags);
404 clear_bit(xfer_id, minfo->xfer_alloc_table);
405 spin_unlock_irqrestore(&minfo->xfer_lock, flags);
406
407 /* Increment the count for the next user to get through */
408 up(&minfo->sem_xfer_count);
409}
410
411/**
412 * ti_sci_do_xfer() - Do one transfer
413 * @info: Pointer to SCI entity information
414 * @xfer: Transfer to initiate and wait for response
415 *
416 * Return: -ETIMEDOUT in case of no response, if transmit error,
417 * return corresponding error, else if all goes well,
418 * return 0.
419 */
420static inline int ti_sci_do_xfer(struct ti_sci_info *info,
421 struct ti_sci_xfer *xfer)
422{
423 int ret;
424 int timeout;
425 struct device *dev = info->dev;
426
427 ret = mbox_send_message(info->chan_tx, &xfer->tx_message);
428 if (ret < 0)
429 return ret;
430
431 ret = 0;
432
433 /* And we wait for the response. */
434 timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms);
435 if (!wait_for_completion_timeout(&xfer->done, timeout)) {
436 dev_err(dev, "Mbox timedout in resp(caller: %pF)\n",
437 (void *)_RET_IP_);
438 ret = -ETIMEDOUT;
439 }
440 /*
441 * NOTE: we might prefer not to need the mailbox ticker to manage the
442 * transfer queueing since the protocol layer queues things by itself.
443 * Unfortunately, we have to kick the mailbox framework after we have
444 * received our message.
445 */
446 mbox_client_txdone(info->chan_tx, ret);
447
448 return ret;
449}
450
451/**
452 * ti_sci_cmd_get_revision() - command to get the revision of the SCI entity
453 * @info: Pointer to SCI entity information
454 *
455 * Updates the SCI information in the internal data structure.
456 *
457 * Return: 0 if all went fine, else return appropriate error.
458 */
459static int ti_sci_cmd_get_revision(struct ti_sci_info *info)
460{
461 struct device *dev = info->dev;
462 struct ti_sci_handle *handle = &info->handle;
463 struct ti_sci_version_info *ver = &handle->version;
464 struct ti_sci_msg_resp_version *rev_info;
465 struct ti_sci_xfer *xfer;
466 int ret;
467
468 /* No need to setup flags since it is expected to respond */
469 xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_VERSION,
470 0x0, sizeof(struct ti_sci_msg_hdr),
471 sizeof(*rev_info));
472 if (IS_ERR(xfer)) {
473 ret = PTR_ERR(xfer);
474 dev_err(dev, "Message alloc failed(%d)\n", ret);
475 return ret;
476 }
477
478 rev_info = (struct ti_sci_msg_resp_version *)xfer->xfer_buf;
479
480 ret = ti_sci_do_xfer(info, xfer);
481 if (ret) {
482 dev_err(dev, "Mbox send fail %d\n", ret);
483 goto fail;
484 }
485
486 ver->abi_major = rev_info->abi_major;
487 ver->abi_minor = rev_info->abi_minor;
488 ver->firmware_revision = rev_info->firmware_revision;
489 strncpy(ver->firmware_description, rev_info->firmware_description,
490 sizeof(ver->firmware_description));
491
492fail:
493 ti_sci_put_one_xfer(&info->minfo, xfer);
494 return ret;
495}
496
497/**
498 * ti_sci_get_handle() - Get the TI SCI handle for a device
499 * @dev: Pointer to device for which we want SCI handle
500 *
501 * NOTE: The function does not track individual clients of the framework
502 * and is expected to be maintained by caller of TI SCI protocol library.
503 * ti_sci_put_handle must be balanced with successful ti_sci_get_handle
504 * Return: pointer to handle if successful, else:
505 * -EPROBE_DEFER if the instance is not ready
506 * -ENODEV if the required node handler is missing
507 * -EINVAL if invalid conditions are encountered.
508 */
509const struct ti_sci_handle *ti_sci_get_handle(struct device *dev)
510{
511 struct device_node *ti_sci_np;
512 struct list_head *p;
513 struct ti_sci_handle *handle = NULL;
514 struct ti_sci_info *info;
515
516 if (!dev) {
517 pr_err("I need a device pointer\n");
518 return ERR_PTR(-EINVAL);
519 }
520 ti_sci_np = of_get_parent(dev->of_node);
521 if (!ti_sci_np) {
522 dev_err(dev, "No OF information\n");
523 return ERR_PTR(-EINVAL);
524 }
525
526 mutex_lock(&ti_sci_list_mutex);
527 list_for_each(p, &ti_sci_list) {
528 info = list_entry(p, struct ti_sci_info, node);
529 if (ti_sci_np == info->dev->of_node) {
530 handle = &info->handle;
531 info->users++;
532 break;
533 }
534 }
535 mutex_unlock(&ti_sci_list_mutex);
536 of_node_put(ti_sci_np);
537
538 if (!handle)
539 return ERR_PTR(-EPROBE_DEFER);
540
541 return handle;
542}
543EXPORT_SYMBOL_GPL(ti_sci_get_handle);
544
545/**
546 * ti_sci_put_handle() - Release the handle acquired by ti_sci_get_handle
547 * @handle: Handle acquired by ti_sci_get_handle
548 *
549 * NOTE: The function does not track individual clients of the framework
550 * and is expected to be maintained by caller of TI SCI protocol library.
551 * ti_sci_put_handle must be balanced with successful ti_sci_get_handle
552 *
553 * Return: 0 is successfully released
554 * if an error pointer was passed, it returns the error value back,
555 * if null was passed, it returns -EINVAL;
556 */
557int ti_sci_put_handle(const struct ti_sci_handle *handle)
558{
559 struct ti_sci_info *info;
560
561 if (IS_ERR(handle))
562 return PTR_ERR(handle);
563 if (!handle)
564 return -EINVAL;
565
566 info = handle_to_ti_sci_info(handle);
567 mutex_lock(&ti_sci_list_mutex);
568 if (!WARN_ON(!info->users))
569 info->users--;
570 mutex_unlock(&ti_sci_list_mutex);
571
572 return 0;
573}
574EXPORT_SYMBOL_GPL(ti_sci_put_handle);
575
576static void devm_ti_sci_release(struct device *dev, void *res)
577{
578 const struct ti_sci_handle **ptr = res;
579 const struct ti_sci_handle *handle = *ptr;
580 int ret;
581
582 ret = ti_sci_put_handle(handle);
583 if (ret)
584 dev_err(dev, "failed to put handle %d\n", ret);
585}
586
587/**
588 * devm_ti_sci_get_handle() - Managed get handle
589 * @dev: device for which we want SCI handle for.
590 *
591 * NOTE: This releases the handle once the device resources are
592 * no longer needed. MUST NOT BE released with ti_sci_put_handle.
593 * The function does not track individual clients of the framework
594 * and is expected to be maintained by caller of TI SCI protocol library.
595 *
596 * Return: 0 if all went fine, else corresponding error.
597 */
598const struct ti_sci_handle *devm_ti_sci_get_handle(struct device *dev)
599{
600 const struct ti_sci_handle **ptr;
601 const struct ti_sci_handle *handle;
602
603 ptr = devres_alloc(devm_ti_sci_release, sizeof(*ptr), GFP_KERNEL);
604 if (!ptr)
605 return ERR_PTR(-ENOMEM);
606 handle = ti_sci_get_handle(dev);
607
608 if (!IS_ERR(handle)) {
609 *ptr = handle;
610 devres_add(dev, ptr);
611 } else {
612 devres_free(ptr);
613 }
614
615 return handle;
616}
617EXPORT_SYMBOL_GPL(devm_ti_sci_get_handle);
618
619/* Description for K2G */
620static const struct ti_sci_desc ti_sci_pmmc_k2g_desc = {
621 .host_id = 2,
622 /* Conservative duration */
623 .max_rx_timeout_ms = 1000,
624 /* Limited by MBOX_TX_QUEUE_LEN. K2G can handle upto 128 messages! */
625 .max_msgs = 20,
626 .max_msg_size = 64,
627};
628
629static const struct of_device_id ti_sci_of_match[] = {
630 {.compatible = "ti,k2g-sci", .data = &ti_sci_pmmc_k2g_desc},
631 { /* Sentinel */ },
632};
633MODULE_DEVICE_TABLE(of, ti_sci_of_match);
634
635static int ti_sci_probe(struct platform_device *pdev)
636{
637 struct device *dev = &pdev->dev;
638 const struct of_device_id *of_id;
639 const struct ti_sci_desc *desc;
640 struct ti_sci_xfer *xfer;
641 struct ti_sci_info *info = NULL;
642 struct ti_sci_xfers_info *minfo;
643 struct mbox_client *cl;
644 int ret = -EINVAL;
645 int i;
646
647 of_id = of_match_device(ti_sci_of_match, dev);
648 if (!of_id) {
649 dev_err(dev, "OF data missing\n");
650 return -EINVAL;
651 }
652 desc = of_id->data;
653
654 info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
655 if (!info)
656 return -ENOMEM;
657
658 info->dev = dev;
659 info->desc = desc;
660 INIT_LIST_HEAD(&info->node);
661 minfo = &info->minfo;
662
663 /*
664 * Pre-allocate messages
665 * NEVER allocate more than what we can indicate in hdr.seq
666 * if we have data description bug, force a fix..
667 */
668 if (WARN_ON(desc->max_msgs >=
669 1 << 8 * sizeof(((struct ti_sci_msg_hdr *)0)->seq)))
670 return -EINVAL;
671
672 minfo->xfer_block = devm_kcalloc(dev,
673 desc->max_msgs,
674 sizeof(*minfo->xfer_block),
675 GFP_KERNEL);
676 if (!minfo->xfer_block)
677 return -ENOMEM;
678
679 minfo->xfer_alloc_table = devm_kzalloc(dev,
680 BITS_TO_LONGS(desc->max_msgs)
681 * sizeof(unsigned long),
682 GFP_KERNEL);
683 if (!minfo->xfer_alloc_table)
684 return -ENOMEM;
685 bitmap_zero(minfo->xfer_alloc_table, desc->max_msgs);
686
687 /* Pre-initialize the buffer pointer to pre-allocated buffers */
688 for (i = 0, xfer = minfo->xfer_block; i < desc->max_msgs; i++, xfer++) {
689 xfer->xfer_buf = devm_kcalloc(dev, 1, desc->max_msg_size,
690 GFP_KERNEL);
691 if (!xfer->xfer_buf)
692 return -ENOMEM;
693
694 xfer->tx_message.buf = xfer->xfer_buf;
695 init_completion(&xfer->done);
696 }
697
698 ret = ti_sci_debugfs_create(pdev, info);
699 if (ret)
700 dev_warn(dev, "Failed to create debug file\n");
701
702 platform_set_drvdata(pdev, info);
703
704 cl = &info->cl;
705 cl->dev = dev;
706 cl->tx_block = false;
707 cl->rx_callback = ti_sci_rx_callback;
708 cl->knows_txdone = true;
709
710 spin_lock_init(&minfo->xfer_lock);
711 sema_init(&minfo->sem_xfer_count, desc->max_msgs);
712
713 info->chan_rx = mbox_request_channel_byname(cl, "rx");
714 if (IS_ERR(info->chan_rx)) {
715 ret = PTR_ERR(info->chan_rx);
716 goto out;
717 }
718
719 info->chan_tx = mbox_request_channel_byname(cl, "tx");
720 if (IS_ERR(info->chan_tx)) {
721 ret = PTR_ERR(info->chan_tx);
722 goto out;
723 }
724 ret = ti_sci_cmd_get_revision(info);
725 if (ret) {
726 dev_err(dev, "Unable to communicate with TISCI(%d)\n", ret);
727 goto out;
728 }
729
730 dev_info(dev, "ABI: %d.%d (firmware rev 0x%04x '%s')\n",
731 info->handle.version.abi_major, info->handle.version.abi_minor,
732 info->handle.version.firmware_revision,
733 info->handle.version.firmware_description);
734
735 mutex_lock(&ti_sci_list_mutex);
736 list_add_tail(&info->node, &ti_sci_list);
737 mutex_unlock(&ti_sci_list_mutex);
738
739 return of_platform_populate(dev->of_node, NULL, NULL, dev);
740out:
741 if (!IS_ERR(info->chan_tx))
742 mbox_free_channel(info->chan_tx);
743 if (!IS_ERR(info->chan_rx))
744 mbox_free_channel(info->chan_rx);
745 debugfs_remove(info->d);
746 return ret;
747}
748
749static int ti_sci_remove(struct platform_device *pdev)
750{
751 struct ti_sci_info *info;
752 struct device *dev = &pdev->dev;
753 int ret = 0;
754
755 of_platform_depopulate(dev);
756
757 info = platform_get_drvdata(pdev);
758
759 mutex_lock(&ti_sci_list_mutex);
760 if (info->users)
761 ret = -EBUSY;
762 else
763 list_del(&info->node);
764 mutex_unlock(&ti_sci_list_mutex);
765
766 if (!ret) {
767 ti_sci_debugfs_destroy(pdev, info);
768
769 /* Safe to free channels since no more users */
770 mbox_free_channel(info->chan_tx);
771 mbox_free_channel(info->chan_rx);
772 }
773
774 return ret;
775}
776
777static struct platform_driver ti_sci_driver = {
778 .probe = ti_sci_probe,
779 .remove = ti_sci_remove,
780 .driver = {
781 .name = "ti-sci",
782 .of_match_table = of_match_ptr(ti_sci_of_match),
783 },
784};
785module_platform_driver(ti_sci_driver);
786
787MODULE_LICENSE("GPL v2");
788MODULE_DESCRIPTION("TI System Control Interface(SCI) driver");
789MODULE_AUTHOR("Nishanth Menon");
790MODULE_ALIAS("platform:ti-sci");
diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h
new file mode 100644
index 000000000000..e9dc53f26e0e
--- /dev/null
+++ b/drivers/firmware/ti_sci.h
@@ -0,0 +1,93 @@
1/*
2 * Texas Instruments System Control Interface (TISCI) Protocol
3 *
4 * Communication protocol with TI SCI hardware
5 * The system works in a message response protocol
6 * See: http://processors.wiki.ti.com/index.php/TISCI for details
7 *
8 * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 *
14 * Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 *
17 * Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the
20 * distribution.
21 *
22 * Neither the name of Texas Instruments Incorporated nor the names of
23 * its contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 *
38 */
39
40#ifndef __TI_SCI_H
41#define __TI_SCI_H
42
43/* Generic Messages */
44#define TI_SCI_MSG_ENABLE_WDT 0x0000
45#define TI_SCI_MSG_WAKE_RESET 0x0001
46#define TI_SCI_MSG_VERSION 0x0002
47#define TI_SCI_MSG_WAKE_REASON 0x0003
48#define TI_SCI_MSG_GOODBYE 0x0004
49
50/**
51 * struct ti_sci_msg_hdr - Generic Message Header for All messages and responses
52 * @type: Type of messages: One of TI_SCI_MSG* values
53 * @host: Host of the message
54 * @seq: Message identifier indicating a transfer sequence
55 * @flags: Flag for the message
56 */
57struct ti_sci_msg_hdr {
58 u16 type;
59 u8 host;
60 u8 seq;
61#define TI_SCI_MSG_FLAG(val) (1 << (val))
62#define TI_SCI_FLAG_REQ_GENERIC_NORESPONSE 0x0
63#define TI_SCI_FLAG_REQ_ACK_ON_RECEIVED TI_SCI_MSG_FLAG(0)
64#define TI_SCI_FLAG_REQ_ACK_ON_PROCESSED TI_SCI_MSG_FLAG(1)
65#define TI_SCI_FLAG_RESP_GENERIC_NACK 0x0
66#define TI_SCI_FLAG_RESP_GENERIC_ACK TI_SCI_MSG_FLAG(1)
67 /* Additional Flags */
68 u32 flags;
69} __packed;
70
71/**
72 * struct ti_sci_msg_resp_version - Response for a message
73 * @hdr: Generic header
74 * @firmware_description: String describing the firmware
75 * @firmware_revision: Firmware revision
76 * @abi_major: Major version of the ABI that firmware supports
77 * @abi_minor: Minor version of the ABI that firmware supports
78 *
79 * In general, ABI version changes follow the rule that minor version increments
80 * are backward compatible. Major revision changes in ABI may not be
81 * backward compatible.
82 *
83 * Response to a generic message with message type TI_SCI_MSG_VERSION
84 */
85struct ti_sci_msg_resp_version {
86 struct ti_sci_msg_hdr hdr;
87 char firmware_description[32];
88 u16 firmware_revision;
89 u8 abi_major;
90 u8 abi_minor;
91} __packed;
92
93#endif /* __TI_SCI_H */
diff --git a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h
new file mode 100644
index 000000000000..e73483fd5327
--- /dev/null
+++ b/include/linux/soc/ti/ti_sci_protocol.h
@@ -0,0 +1,69 @@
1/*
2 * Texas Instruments System Control Interface Protocol
3 *
4 * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
5 * Nishanth Menon
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#ifndef __TISCI_PROTOCOL_H
18#define __TISCI_PROTOCOL_H
19
20/**
21 * struct ti_sci_version_info - version information structure
22 * @abi_major: Major ABI version. Change here implies risk of backward
23 * compatibility break.
24 * @abi_minor: Minor ABI version. Change here implies new feature addition,
25 * or compatible change in ABI.
26 * @firmware_revision: Firmware revision (not usually used).
27 * @firmware_description: Firmware description (not usually used).
28 */
29struct ti_sci_version_info {
30 u8 abi_major;
31 u8 abi_minor;
32 u16 firmware_revision;
33 char firmware_description[32];
34};
35
36/**
37 * struct ti_sci_handle - Handle returned to TI SCI clients for usage.
38 * @version: structure containing version information
39 */
40struct ti_sci_handle {
41 struct ti_sci_version_info version;
42};
43
44#if IS_ENABLED(CONFIG_TI_SCI_PROTOCOL)
45const struct ti_sci_handle *ti_sci_get_handle(struct device *dev);
46int ti_sci_put_handle(const struct ti_sci_handle *handle);
47const struct ti_sci_handle *devm_ti_sci_get_handle(struct device *dev);
48
49#else /* CONFIG_TI_SCI_PROTOCOL */
50
51static inline const struct ti_sci_handle *ti_sci_get_handle(struct device *dev)
52{
53 return ERR_PTR(-EINVAL);
54}
55
56static inline int ti_sci_put_handle(const struct ti_sci_handle *handle)
57{
58 return -EINVAL;
59}
60
61static inline
62const struct ti_sci_handle *devm_ti_sci_get_handle(struct device *dev)
63{
64 return ERR_PTR(-EINVAL);
65}
66
67#endif /* CONFIG_TI_SCI_PROTOCOL */
68
69#endif /* __TISCI_PROTOCOL_H */