^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * OMAP Remote Processor driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2011-2020 Texas Instruments Incorporated - http://www.ti.com/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2011 Google, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Ohad Ben-Cohen <ohad@wizery.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Brian Swetland <swetland@google.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Fernando Guzman Lugo <fernando.lugo@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Mark Grosen <mgrosen@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Suman Anna <s-anna@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Hari Kanigeri <h-kanigeri2@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/clk/ti.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/of_reserved_mem.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/dma-mapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/remoteproc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/mailbox_client.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/omap-iommu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/omap-mailbox.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/mfd/syscon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/reset.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <clocksource/timer-ti-dm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/platform_data/dmtimer-omap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include "omap_remoteproc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include "remoteproc_internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /* default auto-suspend delay (ms) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define DEFAULT_AUTOSUSPEND_DELAY 10000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * struct omap_rproc_boot_data - boot data structure for the DSP omap rprocs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * @syscon: regmap handle for the system control configuration module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * @boot_reg: boot register offset within the @syscon regmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * @boot_reg_shift: bit-field shift required for the boot address value in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * @boot_reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct omap_rproc_boot_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct regmap *syscon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) unsigned int boot_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) unsigned int boot_reg_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * struct omap_rproc_mem - internal memory structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * @cpu_addr: MPU virtual address of the memory region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * @bus_addr: bus address used to access the memory region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * @dev_addr: device address of the memory region from DSP view
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * @size: size of the memory region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct omap_rproc_mem {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) void __iomem *cpu_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) phys_addr_t bus_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) u32 dev_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) size_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * struct omap_rproc_timer - data structure for a timer used by a omap rproc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * @odt: timer pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * @timer_ops: OMAP dmtimer ops for @odt timer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * @irq: timer irq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct omap_rproc_timer {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct omap_dm_timer *odt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) const struct omap_dm_timer_ops *timer_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * struct omap_rproc - omap remote processor state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * @mbox: mailbox channel handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * @client: mailbox client to request the mailbox channel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * @boot_data: boot data structure for setting processor boot address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * @mem: internal memory regions data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * @num_mems: number of internal memory regions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * @num_timers: number of rproc timer(s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * @num_wd_timers: number of rproc watchdog timers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * @timers: timer(s) info used by rproc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * @autosuspend_delay: auto-suspend delay value to be used for runtime pm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * @need_resume: if true a resume is needed in the system resume callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * @rproc: rproc handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * @reset: reset handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * @pm_comp: completion primitive to sync for suspend response
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * @fck: functional clock for the remoteproc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * @suspend_acked: state machine flag to store the suspend request ack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct omap_rproc {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct mbox_chan *mbox;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct mbox_client client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct omap_rproc_boot_data *boot_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct omap_rproc_mem *mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) int num_mems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) int num_timers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) int num_wd_timers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) struct omap_rproc_timer *timers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) int autosuspend_delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) bool need_resume;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct rproc *rproc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct reset_control *reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct completion pm_comp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct clk *fck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) bool suspend_acked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * struct omap_rproc_mem_data - memory definitions for an omap remote processor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * @name: name for this memory entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * @dev_addr: device address for the memory entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) struct omap_rproc_mem_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) const u32 dev_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * struct omap_rproc_dev_data - device data for the omap remote processor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * @device_name: device name of the remote processor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * @mems: memory definitions for this remote processor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) struct omap_rproc_dev_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) const char *device_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) const struct omap_rproc_mem_data *mems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * omap_rproc_request_timer() - request a timer for a remoteproc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * @dev: device requesting the timer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * @np: device node pointer to the desired timer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * @timer: handle to a struct omap_rproc_timer to return the timer handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * This helper function is used primarily to request a timer associated with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * a remoteproc. The returned handle is stored in the .odt field of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * @timer structure passed in, and is used to invoke other timer specific
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * ops (like starting a timer either during device initialization or during
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * a resume operation, or for stopping/freeing a timer).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * Return: 0 on success, otherwise an appropriate failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static int omap_rproc_request_timer(struct device *dev, struct device_node *np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) struct omap_rproc_timer *timer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) timer->odt = timer->timer_ops->request_by_node(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (!timer->odt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) dev_err(dev, "request for timer node %p failed\n", np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) ret = timer->timer_ops->set_source(timer->odt, OMAP_TIMER_SRC_SYS_CLK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) dev_err(dev, "error setting OMAP_TIMER_SRC_SYS_CLK as source for timer node %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) timer->timer_ops->free(timer->odt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) /* clean counter, remoteproc code will set the value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) timer->timer_ops->set_load(timer->odt, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * omap_rproc_start_timer() - start a timer for a remoteproc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * @timer: handle to a OMAP rproc timer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * This helper function is used to start a timer associated with a remoteproc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * obtained using the request_timer ops. The helper function needs to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * invoked by the driver to start the timer (during device initialization)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * or to just resume the timer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * Return: 0 on success, otherwise a failure as returned by DMTimer ops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) static inline int omap_rproc_start_timer(struct omap_rproc_timer *timer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return timer->timer_ops->start(timer->odt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * omap_rproc_stop_timer() - stop a timer for a remoteproc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * @timer: handle to a OMAP rproc timer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * This helper function is used to disable a timer associated with a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * remoteproc, and needs to be called either during a device shutdown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * or suspend operation. The separate helper function allows the driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * to just stop a timer without having to release the timer during a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * suspend operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * Return: 0 on success, otherwise a failure as returned by DMTimer ops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) static inline int omap_rproc_stop_timer(struct omap_rproc_timer *timer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return timer->timer_ops->stop(timer->odt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * omap_rproc_release_timer() - release a timer for a remoteproc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * @timer: handle to a OMAP rproc timer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) * This helper function is used primarily to release a timer associated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * with a remoteproc. The dmtimer will be available for other clients to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * use once released.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) * Return: 0 on success, otherwise a failure as returned by DMTimer ops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) static inline int omap_rproc_release_timer(struct omap_rproc_timer *timer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return timer->timer_ops->free(timer->odt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * omap_rproc_get_timer_irq() - get the irq for a timer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * @timer: handle to a OMAP rproc timer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) * This function is used to get the irq associated with a watchdog timer. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * function is called by the OMAP remoteproc driver to register a interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * handler to handle watchdog events on the remote processor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * Return: irq id on success, otherwise a failure as returned by DMTimer ops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) static inline int omap_rproc_get_timer_irq(struct omap_rproc_timer *timer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return timer->timer_ops->get_irq(timer->odt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * omap_rproc_ack_timer_irq() - acknowledge a timer irq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * @timer: handle to a OMAP rproc timer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * This function is used to clear the irq associated with a watchdog timer. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * The function is called by the OMAP remoteproc upon a watchdog event on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * remote processor to clear the interrupt status of the watchdog timer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) static inline void omap_rproc_ack_timer_irq(struct omap_rproc_timer *timer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) timer->timer_ops->write_status(timer->odt, OMAP_TIMER_INT_OVERFLOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * omap_rproc_watchdog_isr() - Watchdog ISR handler for remoteproc device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * @irq: IRQ number associated with a watchdog timer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * @data: IRQ handler data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) * This ISR routine executes the required necessary low-level code to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) * acknowledge a watchdog timer interrupt. There can be multiple watchdog
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * timers associated with a rproc (like IPUs which have 2 watchdog timers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) * one per Cortex M3/M4 core), so a lookup has to be performed to identify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * the timer to acknowledge its interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) * The function also invokes rproc_report_crash to report the watchdog event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * to the remoteproc driver core, to trigger a recovery.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * Return: IRQ_HANDLED on success, otherwise IRQ_NONE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) static irqreturn_t omap_rproc_watchdog_isr(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) struct rproc *rproc = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) struct omap_rproc *oproc = rproc->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) struct device *dev = rproc->dev.parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) struct omap_rproc_timer *timers = oproc->timers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) struct omap_rproc_timer *wd_timer = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) int num_timers = oproc->num_timers + oproc->num_wd_timers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) for (i = oproc->num_timers; i < num_timers; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (timers[i].irq > 0 && irq == timers[i].irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) wd_timer = &timers[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (!wd_timer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) dev_err(dev, "invalid timer\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) omap_rproc_ack_timer_irq(wd_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) rproc_report_crash(rproc, RPROC_WATCHDOG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * omap_rproc_enable_timers() - enable the timers for a remoteproc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * @rproc: handle of a remote processor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * @configure: boolean flag used to acquire and configure the timer handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) * This function is used primarily to enable the timers associated with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * a remoteproc. The configure flag is provided to allow the driver to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * to either acquire and start a timer (during device initialization) or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) * to just start a timer (during a resume operation).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) * Return: 0 on success, otherwise an appropriate failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) static int omap_rproc_enable_timers(struct rproc *rproc, bool configure)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) struct platform_device *tpdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) struct dmtimer_platform_data *tpdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) const struct omap_dm_timer_ops *timer_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) struct omap_rproc *oproc = rproc->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) struct omap_rproc_timer *timers = oproc->timers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) struct device *dev = rproc->dev.parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) struct device_node *np = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) int num_timers = oproc->num_timers + oproc->num_wd_timers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (!num_timers)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (!configure)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) goto start_timers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) for (i = 0; i < num_timers; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (i < oproc->num_timers)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) np = of_parse_phandle(dev->of_node, "ti,timers", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) np = of_parse_phandle(dev->of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) "ti,watchdog-timers",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) (i - oproc->num_timers));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (!np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) ret = -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) dev_err(dev, "device node lookup for timer at index %d failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) i < oproc->num_timers ? i :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) i - oproc->num_timers, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) goto free_timers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) tpdev = of_find_device_by_node(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (!tpdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) dev_err(dev, "could not get timer platform device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) goto put_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) tpdata = dev_get_platdata(&tpdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) put_device(&tpdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (!tpdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) dev_err(dev, "dmtimer pdata structure NULL\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) goto put_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) timer_ops = tpdata->timer_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (!timer_ops || !timer_ops->request_by_node ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) !timer_ops->set_source || !timer_ops->set_load ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) !timer_ops->free || !timer_ops->start ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) !timer_ops->stop || !timer_ops->get_irq ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) !timer_ops->write_status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) dev_err(dev, "device does not have required timer ops\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) goto put_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) timers[i].irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) timers[i].timer_ops = timer_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) ret = omap_rproc_request_timer(dev, np, &timers[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) dev_err(dev, "request for timer %p failed: %d\n", np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) goto put_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) of_node_put(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (i >= oproc->num_timers) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) timers[i].irq = omap_rproc_get_timer_irq(&timers[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (timers[i].irq < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) dev_err(dev, "get_irq for timer %p failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) np, timers[i].irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) goto free_timers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) ret = request_irq(timers[i].irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) omap_rproc_watchdog_isr, IRQF_SHARED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) "rproc-wdt", rproc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) dev_err(dev, "error requesting irq for timer %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) omap_rproc_release_timer(&timers[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) timers[i].odt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) timers[i].timer_ops = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) timers[i].irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) goto free_timers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) start_timers:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) for (i = 0; i < num_timers; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) ret = omap_rproc_start_timer(&timers[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) dev_err(dev, "start timer %p failed failed: %d\n", np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) while (i >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) omap_rproc_stop_timer(&timers[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) i--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) goto put_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) put_node:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if (configure)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) of_node_put(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) free_timers:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) while (i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if (i >= oproc->num_timers)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) free_irq(timers[i].irq, rproc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) omap_rproc_release_timer(&timers[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) timers[i].odt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) timers[i].timer_ops = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) timers[i].irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) * omap_rproc_disable_timers() - disable the timers for a remoteproc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) * @rproc: handle of a remote processor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) * @configure: boolean flag used to release the timer handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) * This function is used primarily to disable the timers associated with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) * a remoteproc. The configure flag is provided to allow the driver to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) * to either stop and release a timer (during device shutdown) or to just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) * stop a timer (during a suspend operation).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) * Return: 0 on success or no timers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) static int omap_rproc_disable_timers(struct rproc *rproc, bool configure)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) struct omap_rproc *oproc = rproc->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) struct omap_rproc_timer *timers = oproc->timers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) int num_timers = oproc->num_timers + oproc->num_wd_timers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (!num_timers)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) for (i = 0; i < num_timers; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) omap_rproc_stop_timer(&timers[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) if (configure) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (i >= oproc->num_timers)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) free_irq(timers[i].irq, rproc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) omap_rproc_release_timer(&timers[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) timers[i].odt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) timers[i].timer_ops = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) timers[i].irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) * omap_rproc_mbox_callback() - inbound mailbox message handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) * @client: mailbox client pointer used for requesting the mailbox channel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) * @data: mailbox payload
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) * This handler is invoked by omap's mailbox driver whenever a mailbox
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) * message is received. Usually, the mailbox payload simply contains
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) * the index of the virtqueue that is kicked by the remote processor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) * and we let remoteproc core handle it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) * In addition to virtqueue indices, we also have some out-of-band values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) * that indicates different events. Those values are deliberately very
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) * big so they don't coincide with virtqueue indices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) static void omap_rproc_mbox_callback(struct mbox_client *client, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) struct omap_rproc *oproc = container_of(client, struct omap_rproc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) struct device *dev = oproc->rproc->dev.parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) const char *name = oproc->rproc->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) u32 msg = (u32)data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) dev_dbg(dev, "mbox msg: 0x%x\n", msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) switch (msg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) case RP_MBOX_CRASH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) * remoteproc detected an exception, notify the rproc core.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) * The remoteproc core will handle the recovery.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) dev_err(dev, "omap rproc %s crashed\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) rproc_report_crash(oproc->rproc, RPROC_FATAL_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) case RP_MBOX_ECHO_REPLY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) dev_info(dev, "received echo reply from %s\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) case RP_MBOX_SUSPEND_ACK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) case RP_MBOX_SUSPEND_CANCEL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) oproc->suspend_acked = msg == RP_MBOX_SUSPEND_ACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) complete(&oproc->pm_comp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) if (msg >= RP_MBOX_READY && msg < RP_MBOX_END_MSG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (msg > oproc->rproc->max_notifyid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) dev_dbg(dev, "dropping unknown message 0x%x", msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) /* msg contains the index of the triggered vring */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) if (rproc_vq_interrupt(oproc->rproc, msg) == IRQ_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) dev_dbg(dev, "no message was found in vqid %d\n", msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) /* kick a virtqueue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) static void omap_rproc_kick(struct rproc *rproc, int vqid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) struct omap_rproc *oproc = rproc->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) struct device *dev = rproc->dev.parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) /* wake up the rproc before kicking it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) ret = pm_runtime_get_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) if (WARN_ON(ret < 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) dev_err(dev, "pm_runtime_get_sync() failed during kick, ret = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) pm_runtime_put_noidle(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) /* send the index of the triggered virtqueue in the mailbox payload */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) ret = mbox_send_message(oproc->mbox, (void *)vqid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) dev_err(dev, "failed to send mailbox message, status = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) pm_runtime_mark_last_busy(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) pm_runtime_put_autosuspend(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) * omap_rproc_write_dsp_boot_addr() - set boot address for DSP remote processor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) * @rproc: handle of a remote processor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) * Set boot address for a supported DSP remote processor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) * Return: 0 on success, or -EINVAL if boot address is not aligned properly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) static int omap_rproc_write_dsp_boot_addr(struct rproc *rproc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) struct device *dev = rproc->dev.parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) struct omap_rproc *oproc = rproc->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) struct omap_rproc_boot_data *bdata = oproc->boot_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) u32 offset = bdata->boot_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) u32 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) if (rproc->bootaddr & (SZ_1K - 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) dev_err(dev, "invalid boot address 0x%llx, must be aligned on a 1KB boundary\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) rproc->bootaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) value = rproc->bootaddr >> bdata->boot_reg_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) mask = ~(SZ_1K - 1) >> bdata->boot_reg_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) return regmap_update_bits(bdata->syscon, offset, mask, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) * Power up the remote processor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) * This function will be invoked only after the firmware for this rproc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) * was loaded, parsed successfully, and all of its resource requirements
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) * were met.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) static int omap_rproc_start(struct rproc *rproc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) struct omap_rproc *oproc = rproc->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) struct device *dev = rproc->dev.parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) struct mbox_client *client = &oproc->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (oproc->boot_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) ret = omap_rproc_write_dsp_boot_addr(rproc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) client->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) client->tx_done = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) client->rx_callback = omap_rproc_mbox_callback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) client->tx_block = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) client->knows_txdone = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) oproc->mbox = mbox_request_channel(client, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (IS_ERR(oproc->mbox)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) dev_err(dev, "mbox_request_channel failed: %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) PTR_ERR(oproc->mbox));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) * Ping the remote processor. this is only for sanity-sake;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) * there is no functional effect whatsoever.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) * Note that the reply will _not_ arrive immediately: this message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) * will wait in the mailbox fifo until the remote processor is booted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) ret = mbox_send_message(oproc->mbox, (void *)RP_MBOX_ECHO_REQUEST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) dev_err(dev, "mbox_send_message failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) goto put_mbox;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) ret = omap_rproc_enable_timers(rproc, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) dev_err(dev, "omap_rproc_enable_timers failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) goto put_mbox;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) ret = reset_control_deassert(oproc->reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) dev_err(dev, "reset control deassert failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) goto disable_timers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) * remote processor is up, so update the runtime pm status and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) * enable the auto-suspend. The device usage count is incremented
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) * manually for balancing it for auto-suspend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) pm_runtime_set_active(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) pm_runtime_use_autosuspend(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) pm_runtime_get_noresume(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) pm_runtime_enable(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) pm_runtime_mark_last_busy(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) pm_runtime_put_autosuspend(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) disable_timers:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) omap_rproc_disable_timers(rproc, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) put_mbox:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) mbox_free_channel(oproc->mbox);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) /* power off the remote processor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) static int omap_rproc_stop(struct rproc *rproc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) struct device *dev = rproc->dev.parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) struct omap_rproc *oproc = rproc->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * cancel any possible scheduled runtime suspend by incrementing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) * the device usage count, and resuming the device. The remoteproc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) * also needs to be woken up if suspended, to avoid the remoteproc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) * OS to continue to remember any context that it has saved, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) * avoid potential issues in misindentifying a subsequent device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) * reboot as a power restore boot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) ret = pm_runtime_get_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) pm_runtime_put_noidle(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) ret = reset_control_assert(oproc->reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) ret = omap_rproc_disable_timers(rproc, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) goto enable_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) mbox_free_channel(oproc->mbox);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) * update the runtime pm states and status now that the remoteproc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) * has stopped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) pm_runtime_disable(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) pm_runtime_dont_use_autosuspend(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) pm_runtime_put_noidle(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) pm_runtime_set_suspended(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) enable_device:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) reset_control_deassert(oproc->reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) /* schedule the next auto-suspend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) pm_runtime_mark_last_busy(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) pm_runtime_put_autosuspend(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) * omap_rproc_da_to_va() - internal memory translation helper
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) * @rproc: remote processor to apply the address translation for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) * @da: device address to translate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) * @len: length of the memory buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) * Custom function implementing the rproc .da_to_va ops to provide address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) * translation (device address to kernel virtual address) for internal RAMs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) * present in a DSP or IPU device). The translated addresses can be used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) * either by the remoteproc core for loading, or by any rpmsg bus drivers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) * Return: translated virtual address in kernel memory space on success,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) * or NULL on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) static void *omap_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) struct omap_rproc *oproc = rproc->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) u32 offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) if (len <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) if (!oproc->num_mems)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) for (i = 0; i < oproc->num_mems; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) if (da >= oproc->mem[i].dev_addr && da + len <=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) oproc->mem[i].dev_addr + oproc->mem[i].size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) offset = da - oproc->mem[i].dev_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) /* __force to make sparse happy with type conversion */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) return (__force void *)(oproc->mem[i].cpu_addr +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) static const struct rproc_ops omap_rproc_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) .start = omap_rproc_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) .stop = omap_rproc_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) .kick = omap_rproc_kick,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) .da_to_va = omap_rproc_da_to_va,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) static bool _is_rproc_in_standby(struct omap_rproc *oproc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) return ti_clk_is_in_standby(oproc->fck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) /* 1 sec is long enough time to let the remoteproc side suspend the device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) #define DEF_SUSPEND_TIMEOUT 1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) static int _omap_rproc_suspend(struct rproc *rproc, bool auto_suspend)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) struct device *dev = rproc->dev.parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) struct omap_rproc *oproc = rproc->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) unsigned long to = msecs_to_jiffies(DEF_SUSPEND_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) unsigned long ta = jiffies + to;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) u32 suspend_msg = auto_suspend ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) RP_MBOX_SUSPEND_AUTO : RP_MBOX_SUSPEND_SYSTEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) reinit_completion(&oproc->pm_comp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) oproc->suspend_acked = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) ret = mbox_send_message(oproc->mbox, (void *)suspend_msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) dev_err(dev, "PM mbox_send_message failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) ret = wait_for_completion_timeout(&oproc->pm_comp, to);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) if (!oproc->suspend_acked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) * The remoteproc side is returning the ACK message before saving the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) * context, because the context saving is performed within a SYS/BIOS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) * function, and it cannot have any inter-dependencies against the IPC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) * layer. Also, as the SYS/BIOS needs to preserve properly the processor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) * register set, sending this ACK or signalling the completion of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) * context save through a shared memory variable can never be the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) * absolute last thing to be executed on the remoteproc side, and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) * MPU cannot use the ACK message as a sync point to put the remoteproc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) * into reset. The only way to ensure that the remote processor has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) * completed saving the context is to check that the module has reached
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) * STANDBY state (after saving the context, the SYS/BIOS executes the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) * appropriate target-specific WFI instruction causing the module to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) * enter STANDBY).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) while (!_is_rproc_in_standby(oproc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) if (time_after(jiffies, ta))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) return -ETIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) ret = reset_control_assert(oproc->reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) dev_err(dev, "reset assert during suspend failed %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) ret = omap_rproc_disable_timers(rproc, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) dev_err(dev, "disabling timers during suspend failed %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) goto enable_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) * IOMMUs would have to be disabled specifically for runtime suspend.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) * They are handled automatically through System PM callbacks for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) * regular system suspend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) if (auto_suspend) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) ret = omap_iommu_domain_deactivate(rproc->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) dev_err(dev, "iommu domain deactivate failed %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) goto enable_timers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) enable_timers:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) /* ignore errors on re-enabling code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) omap_rproc_enable_timers(rproc, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) enable_device:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) reset_control_deassert(oproc->reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) static int _omap_rproc_resume(struct rproc *rproc, bool auto_suspend)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) struct device *dev = rproc->dev.parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) struct omap_rproc *oproc = rproc->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) * IOMMUs would have to be enabled specifically for runtime resume.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) * They would have been already enabled automatically through System
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) * PM callbacks for regular system resume
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) if (auto_suspend) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) ret = omap_iommu_domain_activate(rproc->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) dev_err(dev, "omap_iommu activate failed %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) /* boot address could be lost after suspend, so restore it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) if (oproc->boot_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) ret = omap_rproc_write_dsp_boot_addr(rproc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) dev_err(dev, "boot address restore failed %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) goto suspend_iommu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) ret = omap_rproc_enable_timers(rproc, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) dev_err(dev, "enabling timers during resume failed %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) goto suspend_iommu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) ret = reset_control_deassert(oproc->reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) dev_err(dev, "reset deassert during resume failed %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) goto disable_timers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) disable_timers:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) omap_rproc_disable_timers(rproc, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) suspend_iommu:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) if (auto_suspend)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) omap_iommu_domain_deactivate(rproc->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) static int __maybe_unused omap_rproc_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) struct platform_device *pdev = to_platform_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) struct rproc *rproc = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) struct omap_rproc *oproc = rproc->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) mutex_lock(&rproc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) if (rproc->state == RPROC_OFFLINE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) if (rproc->state == RPROC_SUSPENDED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) if (rproc->state != RPROC_RUNNING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) ret = _omap_rproc_suspend(rproc, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) dev_err(dev, "suspend failed %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) * remoteproc is running at the time of system suspend, so remember
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) * it so as to wake it up during system resume
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) oproc->need_resume = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) rproc->state = RPROC_SUSPENDED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) mutex_unlock(&rproc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) static int __maybe_unused omap_rproc_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) struct platform_device *pdev = to_platform_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) struct rproc *rproc = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) struct omap_rproc *oproc = rproc->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) mutex_lock(&rproc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) if (rproc->state == RPROC_OFFLINE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) if (rproc->state != RPROC_SUSPENDED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) * remoteproc was auto-suspended at the time of system suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) * so no need to wake-up the processor (leave it in suspended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) * state, will be woken up during a subsequent runtime_resume)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) if (!oproc->need_resume)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) ret = _omap_rproc_resume(rproc, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) dev_err(dev, "resume failed %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) oproc->need_resume = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) rproc->state = RPROC_RUNNING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) pm_runtime_mark_last_busy(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) mutex_unlock(&rproc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) static int omap_rproc_runtime_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) struct rproc *rproc = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) struct omap_rproc *oproc = rproc->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) mutex_lock(&rproc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) if (rproc->state == RPROC_CRASHED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) dev_dbg(dev, "rproc cannot be runtime suspended when crashed!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) if (WARN_ON(rproc->state != RPROC_RUNNING)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) dev_err(dev, "rproc cannot be runtime suspended when not running!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) * do not even attempt suspend if the remote processor is not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) * idled for runtime auto-suspend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) if (!_is_rproc_in_standby(oproc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) goto abort;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) ret = _omap_rproc_suspend(rproc, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) goto abort;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) rproc->state = RPROC_SUSPENDED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) mutex_unlock(&rproc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) abort:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) pm_runtime_mark_last_busy(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) mutex_unlock(&rproc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) static int omap_rproc_runtime_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) struct rproc *rproc = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) mutex_lock(&rproc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) if (WARN_ON(rproc->state != RPROC_SUSPENDED)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) dev_err(dev, "rproc cannot be runtime resumed if not suspended! state=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) rproc->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) ret = _omap_rproc_resume(rproc, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) dev_err(dev, "runtime resume failed %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) rproc->state = RPROC_RUNNING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) mutex_unlock(&rproc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) #endif /* CONFIG_PM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) static const struct omap_rproc_mem_data ipu_mems[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) { .name = "l2ram", .dev_addr = 0x20000000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) static const struct omap_rproc_mem_data dra7_dsp_mems[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) { .name = "l2ram", .dev_addr = 0x800000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) { .name = "l1pram", .dev_addr = 0xe00000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) { .name = "l1dram", .dev_addr = 0xf00000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) static const struct omap_rproc_dev_data omap4_dsp_dev_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) .device_name = "dsp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) static const struct omap_rproc_dev_data omap4_ipu_dev_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) .device_name = "ipu",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) .mems = ipu_mems,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) static const struct omap_rproc_dev_data omap5_dsp_dev_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) .device_name = "dsp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) static const struct omap_rproc_dev_data omap5_ipu_dev_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) .device_name = "ipu",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) .mems = ipu_mems,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) static const struct omap_rproc_dev_data dra7_dsp_dev_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) .device_name = "dsp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) .mems = dra7_dsp_mems,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) static const struct omap_rproc_dev_data dra7_ipu_dev_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) .device_name = "ipu",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) .mems = ipu_mems,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) static const struct of_device_id omap_rproc_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) .compatible = "ti,omap4-dsp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) .data = &omap4_dsp_dev_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) .compatible = "ti,omap4-ipu",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) .data = &omap4_ipu_dev_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) .compatible = "ti,omap5-dsp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) .data = &omap5_dsp_dev_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) .compatible = "ti,omap5-ipu",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) .data = &omap5_ipu_dev_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) .compatible = "ti,dra7-dsp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) .data = &dra7_dsp_dev_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) .compatible = "ti,dra7-ipu",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) .data = &dra7_ipu_dev_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) /* end */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) MODULE_DEVICE_TABLE(of, omap_rproc_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) static const char *omap_rproc_get_firmware(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) const char *fw_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) ret = of_property_read_string(pdev->dev.of_node, "firmware-name",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) &fw_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) return fw_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) static int omap_rproc_get_boot_data(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) struct rproc *rproc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) struct device_node *np = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) struct omap_rproc *oproc = rproc->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) const struct omap_rproc_dev_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) data = of_device_get_match_data(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) if (!of_property_read_bool(np, "ti,bootreg"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) oproc->boot_data = devm_kzalloc(&pdev->dev, sizeof(*oproc->boot_data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) if (!oproc->boot_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) oproc->boot_data->syscon =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) syscon_regmap_lookup_by_phandle(np, "ti,bootreg");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) if (IS_ERR(oproc->boot_data->syscon)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) ret = PTR_ERR(oproc->boot_data->syscon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) if (of_property_read_u32_index(np, "ti,bootreg", 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) &oproc->boot_data->boot_reg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) dev_err(&pdev->dev, "couldn't get the boot register\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) of_property_read_u32_index(np, "ti,bootreg", 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) &oproc->boot_data->boot_reg_shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) static int omap_rproc_of_get_internal_memories(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) struct rproc *rproc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) struct omap_rproc *oproc = rproc->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) const struct omap_rproc_dev_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) int num_mems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) data = of_device_get_match_data(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) if (!data->mems)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) num_mems = of_property_count_elems_of_size(dev->of_node, "reg",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) sizeof(u32)) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) oproc->mem = devm_kcalloc(dev, num_mems, sizeof(*oproc->mem),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) if (!oproc->mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) for (i = 0; data->mems[i].name; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) data->mems[i].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) if (!res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) dev_err(dev, "no memory defined for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) data->mems[i].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) oproc->mem[i].cpu_addr = devm_ioremap_resource(dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) if (IS_ERR(oproc->mem[i].cpu_addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) dev_err(dev, "failed to parse and map %s memory\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) data->mems[i].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) return PTR_ERR(oproc->mem[i].cpu_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) oproc->mem[i].bus_addr = res->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) oproc->mem[i].dev_addr = data->mems[i].dev_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) oproc->mem[i].size = resource_size(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) dev_dbg(dev, "memory %8s: bus addr %pa size 0x%x va %pK da 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) data->mems[i].name, &oproc->mem[i].bus_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) oproc->mem[i].size, oproc->mem[i].cpu_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) oproc->mem[i].dev_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) oproc->num_mems = num_mems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) #ifdef CONFIG_OMAP_REMOTEPROC_WATCHDOG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) static int omap_rproc_count_wdog_timers(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) struct device_node *np = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) ret = of_count_phandle_with_args(np, "ti,watchdog-timers", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) if (ret <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) dev_dbg(dev, "device does not have watchdog timers, status = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) static int omap_rproc_count_wdog_timers(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) static int omap_rproc_of_get_timers(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) struct rproc *rproc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) struct device_node *np = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) struct omap_rproc *oproc = rproc->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) int num_timers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) * Timer nodes are directly used in client nodes as phandles, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) * retrieve the count using appropriate size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) oproc->num_timers = of_count_phandle_with_args(np, "ti,timers", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) if (oproc->num_timers <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) dev_dbg(dev, "device does not have timers, status = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) oproc->num_timers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) oproc->num_timers = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) oproc->num_wd_timers = omap_rproc_count_wdog_timers(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) num_timers = oproc->num_timers + oproc->num_wd_timers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) if (num_timers) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) oproc->timers = devm_kcalloc(dev, num_timers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) sizeof(*oproc->timers),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) if (!oproc->timers)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) dev_dbg(dev, "device has %d tick timers and %d watchdog timers\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) oproc->num_timers, oproc->num_wd_timers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) static int omap_rproc_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) struct device_node *np = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) struct omap_rproc *oproc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) struct rproc *rproc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) const char *firmware;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) struct reset_control *reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) if (!np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) dev_err(&pdev->dev, "only DT-based devices are supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) reset = devm_reset_control_array_get_exclusive(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) if (IS_ERR(reset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) return PTR_ERR(reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) firmware = omap_rproc_get_firmware(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) if (IS_ERR(firmware))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) return PTR_ERR(firmware);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) dev_err(&pdev->dev, "dma_set_coherent_mask: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) rproc = rproc_alloc(&pdev->dev, dev_name(&pdev->dev), &omap_rproc_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) firmware, sizeof(*oproc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) if (!rproc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) oproc = rproc->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) oproc->rproc = rproc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) oproc->reset = reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) /* All existing OMAP IPU and DSP processors have an MMU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) rproc->has_iommu = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) ret = omap_rproc_of_get_internal_memories(pdev, rproc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) goto free_rproc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) ret = omap_rproc_get_boot_data(pdev, rproc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) goto free_rproc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) ret = omap_rproc_of_get_timers(pdev, rproc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) goto free_rproc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) init_completion(&oproc->pm_comp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) oproc->autosuspend_delay = DEFAULT_AUTOSUSPEND_DELAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) of_property_read_u32(pdev->dev.of_node, "ti,autosuspend-delay-ms",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) &oproc->autosuspend_delay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) pm_runtime_set_autosuspend_delay(&pdev->dev, oproc->autosuspend_delay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) oproc->fck = devm_clk_get(&pdev->dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) if (IS_ERR(oproc->fck)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) ret = PTR_ERR(oproc->fck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) goto free_rproc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) ret = of_reserved_mem_device_init(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) dev_warn(&pdev->dev, "device does not have specific CMA pool.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) dev_warn(&pdev->dev, "Typically this should be provided,\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) dev_warn(&pdev->dev, "only omit if you know what you are doing.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) platform_set_drvdata(pdev, rproc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) ret = rproc_add(rproc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) goto release_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) release_mem:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) of_reserved_mem_device_release(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) free_rproc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) rproc_free(rproc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) static int omap_rproc_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) struct rproc *rproc = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) rproc_del(rproc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) rproc_free(rproc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) of_reserved_mem_device_release(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) static const struct dev_pm_ops omap_rproc_pm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) SET_SYSTEM_SLEEP_PM_OPS(omap_rproc_suspend, omap_rproc_resume)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) SET_RUNTIME_PM_OPS(omap_rproc_runtime_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) omap_rproc_runtime_resume, NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) static struct platform_driver omap_rproc_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) .probe = omap_rproc_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) .remove = omap_rproc_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) .name = "omap-rproc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) .pm = &omap_rproc_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) .of_match_table = omap_rproc_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) module_platform_driver(omap_rproc_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) MODULE_DESCRIPTION("OMAP Remote Processor control driver");