1 // SPDX-License-Identifier: GPL-2.0-only
3 * TI Keystone DSP remoteproc driver
5 * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com/
8 #include <linux/module.h>
9 #include <linux/slab.h>
11 #include <linux/interrupt.h>
12 #include <linux/platform_device.h>
13 #include <linux/pm_runtime.h>
14 #include <linux/workqueue.h>
15 #include <linux/of_address.h>
16 #include <linux/of_reserved_mem.h>
17 #include <linux/of_gpio.h>
18 #include <linux/regmap.h>
19 #include <linux/mfd/syscon.h>
20 #include <linux/remoteproc.h>
21 #include <linux/reset.h>
23 #include "remoteproc_internal.h"
25 #define KEYSTONE_RPROC_LOCAL_ADDRESS_MASK (SZ_16M - 1)
28 * struct keystone_rproc_mem - internal memory structure
29 * @cpu_addr: MPU virtual address of the memory region
30 * @bus_addr: Bus address used to access the memory region
31 * @dev_addr: Device address of the memory region from DSP view
32 * @size: Size of the memory region
34 struct keystone_rproc_mem
{
35 void __iomem
*cpu_addr
;
42 * struct keystone_rproc - keystone remote processor driver structure
43 * @dev: cached device pointer
44 * @rproc: remoteproc device handle
45 * @mem: internal memory regions data
46 * @num_mems: number of internal memory regions
47 * @dev_ctrl: device control regmap handle
48 * @reset: reset control handle
49 * @boot_offset: boot register offset in @dev_ctrl regmap
50 * @irq_ring: irq entry for vring
51 * @irq_fault: irq entry for exception
52 * @kick_gpio: gpio used for virtio kicks
53 * @workqueue: workqueue for processing virtio interrupts
55 struct keystone_rproc
{
58 struct keystone_rproc_mem
*mem
;
60 struct regmap
*dev_ctrl
;
61 struct reset_control
*reset
;
66 struct work_struct workqueue
;
69 /* Put the DSP processor into reset */
70 static void keystone_rproc_dsp_reset(struct keystone_rproc
*ksproc
)
72 reset_control_assert(ksproc
->reset
);
75 /* Configure the boot address and boot the DSP processor */
76 static int keystone_rproc_dsp_boot(struct keystone_rproc
*ksproc
, u32 boot_addr
)
80 if (boot_addr
& (SZ_1K
- 1)) {
81 dev_err(ksproc
->dev
, "invalid boot address 0x%x, must be aligned on a 1KB boundary\n",
86 ret
= regmap_write(ksproc
->dev_ctrl
, ksproc
->boot_offset
, boot_addr
);
88 dev_err(ksproc
->dev
, "regmap_write of boot address failed, status = %d\n",
93 reset_control_deassert(ksproc
->reset
);
99 * Process the remoteproc exceptions
101 * The exception reporting on Keystone DSP remote processors is very simple
102 * compared to the equivalent processors on the OMAP family, it is notified
103 * through a software-designed specific interrupt source in the IPC interrupt
104 * generation register.
106 * This function just invokes the rproc_report_crash to report the exception
107 * to the remoteproc driver core, to trigger a recovery.
109 static irqreturn_t
keystone_rproc_exception_interrupt(int irq
, void *dev_id
)
111 struct keystone_rproc
*ksproc
= dev_id
;
113 rproc_report_crash(ksproc
->rproc
, RPROC_FATAL_ERROR
);
119 * Main virtqueue message workqueue function
121 * This function is executed upon scheduling of the keystone remoteproc
122 * driver's workqueue. The workqueue is scheduled by the vring ISR handler.
124 * There is no payload message indicating the virtqueue index as is the
125 * case with mailbox-based implementations on OMAP family. As such, this
126 * handler processes both the Tx and Rx virtqueue indices on every invocation.
127 * The rproc_vq_interrupt function can detect if there are new unprocessed
128 * messages or not (returns IRQ_NONE vs IRQ_HANDLED), but there is no need
129 * to check for these return values. The index 0 triggering will process all
130 * pending Rx buffers, and the index 1 triggering will process all newly
131 * available Tx buffers and will wakeup any potentially blocked senders.
134 * 1. A payload could be added by using some of the source bits in the
135 * IPC interrupt generation registers, but this would need additional
136 * changes to the overall IPC stack, and currently there are no benefits
137 * of adapting that approach.
138 * 2. The current logic is based on an inherent design assumption of supporting
139 * only 2 vrings, but this can be changed if needed.
141 static void handle_event(struct work_struct
*work
)
143 struct keystone_rproc
*ksproc
=
144 container_of(work
, struct keystone_rproc
, workqueue
);
146 rproc_vq_interrupt(ksproc
->rproc
, 0);
147 rproc_vq_interrupt(ksproc
->rproc
, 1);
151 * Interrupt handler for processing vring kicks from remote processor
153 static irqreturn_t
keystone_rproc_vring_interrupt(int irq
, void *dev_id
)
155 struct keystone_rproc
*ksproc
= dev_id
;
157 schedule_work(&ksproc
->workqueue
);
163 * Power up the DSP remote processor.
165 * This function will be invoked only after the firmware for this rproc
166 * was loaded, parsed successfully, and all of its resource requirements
169 static int keystone_rproc_start(struct rproc
*rproc
)
171 struct keystone_rproc
*ksproc
= rproc
->priv
;
174 INIT_WORK(&ksproc
->workqueue
, handle_event
);
176 ret
= request_irq(ksproc
->irq_ring
, keystone_rproc_vring_interrupt
, 0,
177 dev_name(ksproc
->dev
), ksproc
);
179 dev_err(ksproc
->dev
, "failed to enable vring interrupt, ret = %d\n",
184 ret
= request_irq(ksproc
->irq_fault
, keystone_rproc_exception_interrupt
,
185 0, dev_name(ksproc
->dev
), ksproc
);
187 dev_err(ksproc
->dev
, "failed to enable exception interrupt, ret = %d\n",
192 ret
= keystone_rproc_dsp_boot(ksproc
, rproc
->bootaddr
);
199 free_irq(ksproc
->irq_fault
, ksproc
);
201 free_irq(ksproc
->irq_ring
, ksproc
);
202 flush_work(&ksproc
->workqueue
);
208 * Stop the DSP remote processor.
210 * This function puts the DSP processor into reset, and finishes processing
211 * of any pending messages.
213 static int keystone_rproc_stop(struct rproc
*rproc
)
215 struct keystone_rproc
*ksproc
= rproc
->priv
;
217 keystone_rproc_dsp_reset(ksproc
);
218 free_irq(ksproc
->irq_fault
, ksproc
);
219 free_irq(ksproc
->irq_ring
, ksproc
);
220 flush_work(&ksproc
->workqueue
);
226 * Kick the remote processor to notify about pending unprocessed messages.
227 * The vqid usage is not used and is inconsequential, as the kick is performed
228 * through a simulated GPIO (a bit in an IPC interrupt-triggering register),
229 * the remote processor is expected to process both its Tx and Rx virtqueues.
231 static void keystone_rproc_kick(struct rproc
*rproc
, int vqid
)
233 struct keystone_rproc
*ksproc
= rproc
->priv
;
235 if (WARN_ON(ksproc
->kick_gpio
< 0))
238 gpio_set_value(ksproc
->kick_gpio
, 1);
242 * Custom function to translate a DSP device address (internal RAMs only) to a
243 * kernel virtual address. The DSPs can access their RAMs at either an internal
244 * address visible only from a DSP, or at the SoC-level bus address. Both these
245 * addresses need to be looked through for translation. The translated addresses
246 * can be used either by the remoteproc core for loading (when using kernel
247 * remoteproc loader), or by any rpmsg bus drivers.
249 static void *keystone_rproc_da_to_va(struct rproc
*rproc
, u64 da
, size_t len
)
251 struct keystone_rproc
*ksproc
= rproc
->priv
;
252 void __iomem
*va
= NULL
;
253 phys_addr_t bus_addr
;
254 u32 dev_addr
, offset
;
261 for (i
= 0; i
< ksproc
->num_mems
; i
++) {
262 bus_addr
= ksproc
->mem
[i
].bus_addr
;
263 dev_addr
= ksproc
->mem
[i
].dev_addr
;
264 size
= ksproc
->mem
[i
].size
;
266 if (da
< KEYSTONE_RPROC_LOCAL_ADDRESS_MASK
) {
267 /* handle DSP-view addresses */
268 if ((da
>= dev_addr
) &&
269 ((da
+ len
) <= (dev_addr
+ size
))) {
270 offset
= da
- dev_addr
;
271 va
= ksproc
->mem
[i
].cpu_addr
+ offset
;
275 /* handle SoC-view addresses */
276 if ((da
>= bus_addr
) &&
277 (da
+ len
) <= (bus_addr
+ size
)) {
278 offset
= da
- bus_addr
;
279 va
= ksproc
->mem
[i
].cpu_addr
+ offset
;
285 return (__force
void *)va
;
288 static const struct rproc_ops keystone_rproc_ops
= {
289 .start
= keystone_rproc_start
,
290 .stop
= keystone_rproc_stop
,
291 .kick
= keystone_rproc_kick
,
292 .da_to_va
= keystone_rproc_da_to_va
,
295 static int keystone_rproc_of_get_memories(struct platform_device
*pdev
,
296 struct keystone_rproc
*ksproc
)
298 static const char * const mem_names
[] = {"l2sram", "l1pram", "l1dram"};
299 struct device
*dev
= &pdev
->dev
;
300 struct resource
*res
;
304 num_mems
= ARRAY_SIZE(mem_names
);
305 ksproc
->mem
= devm_kcalloc(ksproc
->dev
, num_mems
,
306 sizeof(*ksproc
->mem
), GFP_KERNEL
);
310 for (i
= 0; i
< num_mems
; i
++) {
311 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
,
313 ksproc
->mem
[i
].cpu_addr
= devm_ioremap_resource(dev
, res
);
314 if (IS_ERR(ksproc
->mem
[i
].cpu_addr
)) {
315 dev_err(dev
, "failed to parse and map %s memory\n",
317 return PTR_ERR(ksproc
->mem
[i
].cpu_addr
);
319 ksproc
->mem
[i
].bus_addr
= res
->start
;
320 ksproc
->mem
[i
].dev_addr
=
321 res
->start
& KEYSTONE_RPROC_LOCAL_ADDRESS_MASK
;
322 ksproc
->mem
[i
].size
= resource_size(res
);
324 /* zero out memories to start in a pristine state */
325 memset((__force
void *)ksproc
->mem
[i
].cpu_addr
, 0,
326 ksproc
->mem
[i
].size
);
328 ksproc
->num_mems
= num_mems
;
333 static int keystone_rproc_of_get_dev_syscon(struct platform_device
*pdev
,
334 struct keystone_rproc
*ksproc
)
336 struct device_node
*np
= pdev
->dev
.of_node
;
337 struct device
*dev
= &pdev
->dev
;
340 if (!of_property_read_bool(np
, "ti,syscon-dev")) {
341 dev_err(dev
, "ti,syscon-dev property is absent\n");
346 syscon_regmap_lookup_by_phandle(np
, "ti,syscon-dev");
347 if (IS_ERR(ksproc
->dev_ctrl
)) {
348 ret
= PTR_ERR(ksproc
->dev_ctrl
);
352 if (of_property_read_u32_index(np
, "ti,syscon-dev", 1,
353 &ksproc
->boot_offset
)) {
354 dev_err(dev
, "couldn't read the boot register offset\n");
361 static int keystone_rproc_probe(struct platform_device
*pdev
)
363 struct device
*dev
= &pdev
->dev
;
364 struct device_node
*np
= dev
->of_node
;
365 struct keystone_rproc
*ksproc
;
368 char *fw_name
= NULL
;
369 char *template = "keystone-dsp%d-fw";
374 dev_err(dev
, "only DT-based devices are supported\n");
378 dsp_id
= of_alias_get_id(np
, "rproc");
380 dev_warn(dev
, "device does not have an alias id\n");
384 /* construct a custom default fw name - subject to change in future */
385 name_len
= strlen(template); /* assuming a single digit alias */
386 fw_name
= devm_kzalloc(dev
, name_len
, GFP_KERNEL
);
389 snprintf(fw_name
, name_len
, template, dsp_id
);
391 rproc
= rproc_alloc(dev
, dev_name(dev
), &keystone_rproc_ops
, fw_name
,
396 rproc
->has_iommu
= false;
397 ksproc
= rproc
->priv
;
398 ksproc
->rproc
= rproc
;
401 ret
= keystone_rproc_of_get_dev_syscon(pdev
, ksproc
);
405 ksproc
->reset
= devm_reset_control_get_exclusive(dev
, NULL
);
406 if (IS_ERR(ksproc
->reset
)) {
407 ret
= PTR_ERR(ksproc
->reset
);
411 /* enable clock for accessing DSP internal memories */
412 pm_runtime_enable(dev
);
413 ret
= pm_runtime_get_sync(dev
);
415 dev_err(dev
, "failed to enable clock, status = %d\n", ret
);
416 pm_runtime_put_noidle(dev
);
420 ret
= keystone_rproc_of_get_memories(pdev
, ksproc
);
424 ksproc
->irq_ring
= platform_get_irq_byname(pdev
, "vring");
425 if (ksproc
->irq_ring
< 0) {
426 ret
= ksproc
->irq_ring
;
430 ksproc
->irq_fault
= platform_get_irq_byname(pdev
, "exception");
431 if (ksproc
->irq_fault
< 0) {
432 ret
= ksproc
->irq_fault
;
436 ksproc
->kick_gpio
= of_get_named_gpio_flags(np
, "kick-gpios", 0, NULL
);
437 if (ksproc
->kick_gpio
< 0) {
438 ret
= ksproc
->kick_gpio
;
439 dev_err(dev
, "failed to get gpio for virtio kicks, status = %d\n",
444 if (of_reserved_mem_device_init(dev
))
445 dev_warn(dev
, "device does not have specific CMA pool\n");
447 /* ensure the DSP is in reset before loading firmware */
448 ret
= reset_control_status(ksproc
->reset
);
450 dev_err(dev
, "failed to get reset status, status = %d\n", ret
);
452 } else if (ret
== 0) {
453 WARN(1, "device is not in reset\n");
454 keystone_rproc_dsp_reset(ksproc
);
457 ret
= rproc_add(rproc
);
459 dev_err(dev
, "failed to add register device with remoteproc core, status = %d\n",
464 platform_set_drvdata(pdev
, ksproc
);
469 of_reserved_mem_device_release(dev
);
471 pm_runtime_put_sync(dev
);
473 pm_runtime_disable(dev
);
479 static int keystone_rproc_remove(struct platform_device
*pdev
)
481 struct keystone_rproc
*ksproc
= platform_get_drvdata(pdev
);
483 rproc_del(ksproc
->rproc
);
484 pm_runtime_put_sync(&pdev
->dev
);
485 pm_runtime_disable(&pdev
->dev
);
486 rproc_free(ksproc
->rproc
);
487 of_reserved_mem_device_release(&pdev
->dev
);
492 static const struct of_device_id keystone_rproc_of_match
[] = {
493 { .compatible
= "ti,k2hk-dsp", },
494 { .compatible
= "ti,k2l-dsp", },
495 { .compatible
= "ti,k2e-dsp", },
496 { .compatible
= "ti,k2g-dsp", },
499 MODULE_DEVICE_TABLE(of
, keystone_rproc_of_match
);
501 static struct platform_driver keystone_rproc_driver
= {
502 .probe
= keystone_rproc_probe
,
503 .remove
= keystone_rproc_remove
,
505 .name
= "keystone-rproc",
506 .of_match_table
= keystone_rproc_of_match
,
510 module_platform_driver(keystone_rproc_driver
);
512 MODULE_AUTHOR("Suman Anna <s-anna@ti.com>");
513 MODULE_LICENSE("GPL v2");
514 MODULE_DESCRIPTION("TI Keystone DSP Remoteproc driver");