Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * OMAP Remote Processor driver
0004  *
0005  * Copyright (C) 2011-2020 Texas Instruments Incorporated - http://www.ti.com/
0006  * Copyright (C) 2011 Google, Inc.
0007  *
0008  * Ohad Ben-Cohen <ohad@wizery.com>
0009  * Brian Swetland <swetland@google.com>
0010  * Fernando Guzman Lugo <fernando.lugo@ti.com>
0011  * Mark Grosen <mgrosen@ti.com>
0012  * Suman Anna <s-anna@ti.com>
0013  * Hari Kanigeri <h-kanigeri2@ti.com>
0014  */
0015 
0016 #include <linux/kernel.h>
0017 #include <linux/module.h>
0018 #include <linux/clk.h>
0019 #include <linux/clk/ti.h>
0020 #include <linux/err.h>
0021 #include <linux/io.h>
0022 #include <linux/of_device.h>
0023 #include <linux/of_reserved_mem.h>
0024 #include <linux/platform_device.h>
0025 #include <linux/pm_runtime.h>
0026 #include <linux/dma-mapping.h>
0027 #include <linux/interrupt.h>
0028 #include <linux/remoteproc.h>
0029 #include <linux/mailbox_client.h>
0030 #include <linux/omap-iommu.h>
0031 #include <linux/omap-mailbox.h>
0032 #include <linux/regmap.h>
0033 #include <linux/mfd/syscon.h>
0034 #include <linux/reset.h>
0035 #include <clocksource/timer-ti-dm.h>
0036 
0037 #include <linux/platform_data/dmtimer-omap.h>
0038 
0039 #include "omap_remoteproc.h"
0040 #include "remoteproc_internal.h"
0041 
0042 /* default auto-suspend delay (ms) */
0043 #define DEFAULT_AUTOSUSPEND_DELAY       10000
0044 
0045 /**
0046  * struct omap_rproc_boot_data - boot data structure for the DSP omap rprocs
0047  * @syscon: regmap handle for the system control configuration module
0048  * @boot_reg: boot register offset within the @syscon regmap
0049  * @boot_reg_shift: bit-field shift required for the boot address value in
0050  *          @boot_reg
0051  */
0052 struct omap_rproc_boot_data {
0053     struct regmap *syscon;
0054     unsigned int boot_reg;
0055     unsigned int boot_reg_shift;
0056 };
0057 
0058 /**
0059  * struct omap_rproc_mem - internal memory structure
0060  * @cpu_addr: MPU virtual address of the memory region
0061  * @bus_addr: bus address used to access the memory region
0062  * @dev_addr: device address of the memory region from DSP view
0063  * @size: size of the memory region
0064  */
0065 struct omap_rproc_mem {
0066     void __iomem *cpu_addr;
0067     phys_addr_t bus_addr;
0068     u32 dev_addr;
0069     size_t size;
0070 };
0071 
0072 /**
0073  * struct omap_rproc_timer - data structure for a timer used by a omap rproc
0074  * @odt: timer pointer
0075  * @timer_ops: OMAP dmtimer ops for @odt timer
0076  * @irq: timer irq
0077  */
0078 struct omap_rproc_timer {
0079     struct omap_dm_timer *odt;
0080     const struct omap_dm_timer_ops *timer_ops;
0081     int irq;
0082 };
0083 
0084 /**
0085  * struct omap_rproc - omap remote processor state
0086  * @mbox: mailbox channel handle
0087  * @client: mailbox client to request the mailbox channel
0088  * @boot_data: boot data structure for setting processor boot address
0089  * @mem: internal memory regions data
0090  * @num_mems: number of internal memory regions
0091  * @num_timers: number of rproc timer(s)
0092  * @num_wd_timers: number of rproc watchdog timers
0093  * @timers: timer(s) info used by rproc
0094  * @autosuspend_delay: auto-suspend delay value to be used for runtime pm
0095  * @need_resume: if true a resume is needed in the system resume callback
0096  * @rproc: rproc handle
0097  * @reset: reset handle
0098  * @pm_comp: completion primitive to sync for suspend response
0099  * @fck: functional clock for the remoteproc
0100  * @suspend_acked: state machine flag to store the suspend request ack
0101  */
0102 struct omap_rproc {
0103     struct mbox_chan *mbox;
0104     struct mbox_client client;
0105     struct omap_rproc_boot_data *boot_data;
0106     struct omap_rproc_mem *mem;
0107     int num_mems;
0108     int num_timers;
0109     int num_wd_timers;
0110     struct omap_rproc_timer *timers;
0111     int autosuspend_delay;
0112     bool need_resume;
0113     struct rproc *rproc;
0114     struct reset_control *reset;
0115     struct completion pm_comp;
0116     struct clk *fck;
0117     bool suspend_acked;
0118 };
0119 
0120 /**
0121  * struct omap_rproc_mem_data - memory definitions for an omap remote processor
0122  * @name: name for this memory entry
0123  * @dev_addr: device address for the memory entry
0124  */
0125 struct omap_rproc_mem_data {
0126     const char *name;
0127     const u32 dev_addr;
0128 };
0129 
0130 /**
0131  * struct omap_rproc_dev_data - device data for the omap remote processor
0132  * @device_name: device name of the remote processor
0133  * @mems: memory definitions for this remote processor
0134  */
0135 struct omap_rproc_dev_data {
0136     const char *device_name;
0137     const struct omap_rproc_mem_data *mems;
0138 };
0139 
0140 /**
0141  * omap_rproc_request_timer() - request a timer for a remoteproc
0142  * @dev: device requesting the timer
0143  * @np: device node pointer to the desired timer
0144  * @timer: handle to a struct omap_rproc_timer to return the timer handle
0145  *
0146  * This helper function is used primarily to request a timer associated with
0147  * a remoteproc. The returned handle is stored in the .odt field of the
0148  * @timer structure passed in, and is used to invoke other timer specific
0149  * ops (like starting a timer either during device initialization or during
0150  * a resume operation, or for stopping/freeing a timer).
0151  *
0152  * Return: 0 on success, otherwise an appropriate failure
0153  */
0154 static int omap_rproc_request_timer(struct device *dev, struct device_node *np,
0155                     struct omap_rproc_timer *timer)
0156 {
0157     int ret;
0158 
0159     timer->odt = timer->timer_ops->request_by_node(np);
0160     if (!timer->odt) {
0161         dev_err(dev, "request for timer node %p failed\n", np);
0162         return -EBUSY;
0163     }
0164 
0165     ret = timer->timer_ops->set_source(timer->odt, OMAP_TIMER_SRC_SYS_CLK);
0166     if (ret) {
0167         dev_err(dev, "error setting OMAP_TIMER_SRC_SYS_CLK as source for timer node %p\n",
0168             np);
0169         timer->timer_ops->free(timer->odt);
0170         return ret;
0171     }
0172 
0173     /* clean counter, remoteproc code will set the value */
0174     timer->timer_ops->set_load(timer->odt, 0);
0175 
0176     return 0;
0177 }
0178 
0179 /**
0180  * omap_rproc_start_timer() - start a timer for a remoteproc
0181  * @timer: handle to a OMAP rproc timer
0182  *
0183  * This helper function is used to start a timer associated with a remoteproc,
0184  * obtained using the request_timer ops. The helper function needs to be
0185  * invoked by the driver to start the timer (during device initialization)
0186  * or to just resume the timer.
0187  *
0188  * Return: 0 on success, otherwise a failure as returned by DMTimer ops
0189  */
0190 static inline int omap_rproc_start_timer(struct omap_rproc_timer *timer)
0191 {
0192     return timer->timer_ops->start(timer->odt);
0193 }
0194 
0195 /**
0196  * omap_rproc_stop_timer() - stop a timer for a remoteproc
0197  * @timer: handle to a OMAP rproc timer
0198  *
0199  * This helper function is used to disable a timer associated with a
0200  * remoteproc, and needs to be called either during a device shutdown
0201  * or suspend operation. The separate helper function allows the driver
0202  * to just stop a timer without having to release the timer during a
0203  * suspend operation.
0204  *
0205  * Return: 0 on success, otherwise a failure as returned by DMTimer ops
0206  */
0207 static inline int omap_rproc_stop_timer(struct omap_rproc_timer *timer)
0208 {
0209     return timer->timer_ops->stop(timer->odt);
0210 }
0211 
0212 /**
0213  * omap_rproc_release_timer() - release a timer for a remoteproc
0214  * @timer: handle to a OMAP rproc timer
0215  *
0216  * This helper function is used primarily to release a timer associated
0217  * with a remoteproc. The dmtimer will be available for other clients to
0218  * use once released.
0219  *
0220  * Return: 0 on success, otherwise a failure as returned by DMTimer ops
0221  */
0222 static inline int omap_rproc_release_timer(struct omap_rproc_timer *timer)
0223 {
0224     return timer->timer_ops->free(timer->odt);
0225 }
0226 
0227 /**
0228  * omap_rproc_get_timer_irq() - get the irq for a timer
0229  * @timer: handle to a OMAP rproc timer
0230  *
0231  * This function is used to get the irq associated with a watchdog timer. The
0232  * function is called by the OMAP remoteproc driver to register a interrupt
0233  * handler to handle watchdog events on the remote processor.
0234  *
0235  * Return: irq id on success, otherwise a failure as returned by DMTimer ops
0236  */
0237 static inline int omap_rproc_get_timer_irq(struct omap_rproc_timer *timer)
0238 {
0239     return timer->timer_ops->get_irq(timer->odt);
0240 }
0241 
0242 /**
0243  * omap_rproc_ack_timer_irq() - acknowledge a timer irq
0244  * @timer: handle to a OMAP rproc timer
0245  *
0246  * This function is used to clear the irq associated with a watchdog timer.
0247  * The function is called by the OMAP remoteproc upon a watchdog event on the
0248  * remote processor to clear the interrupt status of the watchdog timer.
0249  */
0250 static inline void omap_rproc_ack_timer_irq(struct omap_rproc_timer *timer)
0251 {
0252     timer->timer_ops->write_status(timer->odt, OMAP_TIMER_INT_OVERFLOW);
0253 }
0254 
0255 /**
0256  * omap_rproc_watchdog_isr() - Watchdog ISR handler for remoteproc device
0257  * @irq: IRQ number associated with a watchdog timer
0258  * @data: IRQ handler data
0259  *
0260  * This ISR routine executes the required necessary low-level code to
0261  * acknowledge a watchdog timer interrupt. There can be multiple watchdog
0262  * timers associated with a rproc (like IPUs which have 2 watchdog timers,
0263  * one per Cortex M3/M4 core), so a lookup has to be performed to identify
0264  * the timer to acknowledge its interrupt.
0265  *
0266  * The function also invokes rproc_report_crash to report the watchdog event
0267  * to the remoteproc driver core, to trigger a recovery.
0268  *
0269  * Return: IRQ_HANDLED on success, otherwise IRQ_NONE
0270  */
0271 static irqreturn_t omap_rproc_watchdog_isr(int irq, void *data)
0272 {
0273     struct rproc *rproc = data;
0274     struct omap_rproc *oproc = rproc->priv;
0275     struct device *dev = rproc->dev.parent;
0276     struct omap_rproc_timer *timers = oproc->timers;
0277     struct omap_rproc_timer *wd_timer = NULL;
0278     int num_timers = oproc->num_timers + oproc->num_wd_timers;
0279     int i;
0280 
0281     for (i = oproc->num_timers; i < num_timers; i++) {
0282         if (timers[i].irq > 0 && irq == timers[i].irq) {
0283             wd_timer = &timers[i];
0284             break;
0285         }
0286     }
0287 
0288     if (!wd_timer) {
0289         dev_err(dev, "invalid timer\n");
0290         return IRQ_NONE;
0291     }
0292 
0293     omap_rproc_ack_timer_irq(wd_timer);
0294 
0295     rproc_report_crash(rproc, RPROC_WATCHDOG);
0296 
0297     return IRQ_HANDLED;
0298 }
0299 
0300 /**
0301  * omap_rproc_enable_timers() - enable the timers for a remoteproc
0302  * @rproc: handle of a remote processor
0303  * @configure: boolean flag used to acquire and configure the timer handle
0304  *
0305  * This function is used primarily to enable the timers associated with
0306  * a remoteproc. The configure flag is provided to allow the driver
0307  * to either acquire and start a timer (during device initialization) or
0308  * to just start a timer (during a resume operation).
0309  *
0310  * Return: 0 on success, otherwise an appropriate failure
0311  */
0312 static int omap_rproc_enable_timers(struct rproc *rproc, bool configure)
0313 {
0314     int i;
0315     int ret = 0;
0316     struct platform_device *tpdev;
0317     struct dmtimer_platform_data *tpdata;
0318     const struct omap_dm_timer_ops *timer_ops;
0319     struct omap_rproc *oproc = rproc->priv;
0320     struct omap_rproc_timer *timers = oproc->timers;
0321     struct device *dev = rproc->dev.parent;
0322     struct device_node *np = NULL;
0323     int num_timers = oproc->num_timers + oproc->num_wd_timers;
0324 
0325     if (!num_timers)
0326         return 0;
0327 
0328     if (!configure)
0329         goto start_timers;
0330 
0331     for (i = 0; i < num_timers; i++) {
0332         if (i < oproc->num_timers)
0333             np = of_parse_phandle(dev->of_node, "ti,timers", i);
0334         else
0335             np = of_parse_phandle(dev->of_node,
0336                           "ti,watchdog-timers",
0337                           (i - oproc->num_timers));
0338         if (!np) {
0339             ret = -ENXIO;
0340             dev_err(dev, "device node lookup for timer at index %d failed: %d\n",
0341                 i < oproc->num_timers ? i :
0342                 i - oproc->num_timers, ret);
0343             goto free_timers;
0344         }
0345 
0346         tpdev = of_find_device_by_node(np);
0347         if (!tpdev) {
0348             ret = -ENODEV;
0349             dev_err(dev, "could not get timer platform device\n");
0350             goto put_node;
0351         }
0352 
0353         tpdata = dev_get_platdata(&tpdev->dev);
0354         put_device(&tpdev->dev);
0355         if (!tpdata) {
0356             ret = -EINVAL;
0357             dev_err(dev, "dmtimer pdata structure NULL\n");
0358             goto put_node;
0359         }
0360 
0361         timer_ops = tpdata->timer_ops;
0362         if (!timer_ops || !timer_ops->request_by_node ||
0363             !timer_ops->set_source || !timer_ops->set_load ||
0364             !timer_ops->free || !timer_ops->start ||
0365             !timer_ops->stop || !timer_ops->get_irq ||
0366             !timer_ops->write_status) {
0367             ret = -EINVAL;
0368             dev_err(dev, "device does not have required timer ops\n");
0369             goto put_node;
0370         }
0371 
0372         timers[i].irq = -1;
0373         timers[i].timer_ops = timer_ops;
0374         ret = omap_rproc_request_timer(dev, np, &timers[i]);
0375         if (ret) {
0376             dev_err(dev, "request for timer %p failed: %d\n", np,
0377                 ret);
0378             goto put_node;
0379         }
0380         of_node_put(np);
0381 
0382         if (i >= oproc->num_timers) {
0383             timers[i].irq = omap_rproc_get_timer_irq(&timers[i]);
0384             if (timers[i].irq < 0) {
0385                 dev_err(dev, "get_irq for timer %p failed: %d\n",
0386                     np, timers[i].irq);
0387                 ret = -EBUSY;
0388                 goto free_timers;
0389             }
0390 
0391             ret = request_irq(timers[i].irq,
0392                       omap_rproc_watchdog_isr, IRQF_SHARED,
0393                       "rproc-wdt", rproc);
0394             if (ret) {
0395                 dev_err(dev, "error requesting irq for timer %p\n",
0396                     np);
0397                 omap_rproc_release_timer(&timers[i]);
0398                 timers[i].odt = NULL;
0399                 timers[i].timer_ops = NULL;
0400                 timers[i].irq = -1;
0401                 goto free_timers;
0402             }
0403         }
0404     }
0405 
0406 start_timers:
0407     for (i = 0; i < num_timers; i++) {
0408         ret = omap_rproc_start_timer(&timers[i]);
0409         if (ret) {
0410             dev_err(dev, "start timer %p failed failed: %d\n", np,
0411                 ret);
0412             break;
0413         }
0414     }
0415     if (ret) {
0416         while (i >= 0) {
0417             omap_rproc_stop_timer(&timers[i]);
0418             i--;
0419         }
0420         goto put_node;
0421     }
0422     return 0;
0423 
0424 put_node:
0425     if (configure)
0426         of_node_put(np);
0427 free_timers:
0428     while (i--) {
0429         if (i >= oproc->num_timers)
0430             free_irq(timers[i].irq, rproc);
0431         omap_rproc_release_timer(&timers[i]);
0432         timers[i].odt = NULL;
0433         timers[i].timer_ops = NULL;
0434         timers[i].irq = -1;
0435     }
0436 
0437     return ret;
0438 }
0439 
0440 /**
0441  * omap_rproc_disable_timers() - disable the timers for a remoteproc
0442  * @rproc: handle of a remote processor
0443  * @configure: boolean flag used to release the timer handle
0444  *
0445  * This function is used primarily to disable the timers associated with
0446  * a remoteproc. The configure flag is provided to allow the driver
0447  * to either stop and release a timer (during device shutdown) or to just
0448  * stop a timer (during a suspend operation).
0449  *
0450  * Return: 0 on success or no timers
0451  */
0452 static int omap_rproc_disable_timers(struct rproc *rproc, bool configure)
0453 {
0454     int i;
0455     struct omap_rproc *oproc = rproc->priv;
0456     struct omap_rproc_timer *timers = oproc->timers;
0457     int num_timers = oproc->num_timers + oproc->num_wd_timers;
0458 
0459     if (!num_timers)
0460         return 0;
0461 
0462     for (i = 0; i < num_timers; i++) {
0463         omap_rproc_stop_timer(&timers[i]);
0464         if (configure) {
0465             if (i >= oproc->num_timers)
0466                 free_irq(timers[i].irq, rproc);
0467             omap_rproc_release_timer(&timers[i]);
0468             timers[i].odt = NULL;
0469             timers[i].timer_ops = NULL;
0470             timers[i].irq = -1;
0471         }
0472     }
0473 
0474     return 0;
0475 }
0476 
0477 /**
0478  * omap_rproc_mbox_callback() - inbound mailbox message handler
0479  * @client: mailbox client pointer used for requesting the mailbox channel
0480  * @data: mailbox payload
0481  *
0482  * This handler is invoked by omap's mailbox driver whenever a mailbox
0483  * message is received. Usually, the mailbox payload simply contains
0484  * the index of the virtqueue that is kicked by the remote processor,
0485  * and we let remoteproc core handle it.
0486  *
0487  * In addition to virtqueue indices, we also have some out-of-band values
0488  * that indicates different events. Those values are deliberately very
0489  * big so they don't coincide with virtqueue indices.
0490  */
0491 static void omap_rproc_mbox_callback(struct mbox_client *client, void *data)
0492 {
0493     struct omap_rproc *oproc = container_of(client, struct omap_rproc,
0494                         client);
0495     struct device *dev = oproc->rproc->dev.parent;
0496     const char *name = oproc->rproc->name;
0497     u32 msg = (u32)data;
0498 
0499     dev_dbg(dev, "mbox msg: 0x%x\n", msg);
0500 
0501     switch (msg) {
0502     case RP_MBOX_CRASH:
0503         /*
0504          * remoteproc detected an exception, notify the rproc core.
0505          * The remoteproc core will handle the recovery.
0506          */
0507         dev_err(dev, "omap rproc %s crashed\n", name);
0508         rproc_report_crash(oproc->rproc, RPROC_FATAL_ERROR);
0509         break;
0510     case RP_MBOX_ECHO_REPLY:
0511         dev_info(dev, "received echo reply from %s\n", name);
0512         break;
0513     case RP_MBOX_SUSPEND_ACK:
0514     case RP_MBOX_SUSPEND_CANCEL:
0515         oproc->suspend_acked = msg == RP_MBOX_SUSPEND_ACK;
0516         complete(&oproc->pm_comp);
0517         break;
0518     default:
0519         if (msg >= RP_MBOX_READY && msg < RP_MBOX_END_MSG)
0520             return;
0521         if (msg > oproc->rproc->max_notifyid) {
0522             dev_dbg(dev, "dropping unknown message 0x%x", msg);
0523             return;
0524         }
0525         /* msg contains the index of the triggered vring */
0526         if (rproc_vq_interrupt(oproc->rproc, msg) == IRQ_NONE)
0527             dev_dbg(dev, "no message was found in vqid %d\n", msg);
0528     }
0529 }
0530 
0531 /* kick a virtqueue */
0532 static void omap_rproc_kick(struct rproc *rproc, int vqid)
0533 {
0534     struct omap_rproc *oproc = rproc->priv;
0535     struct device *dev = rproc->dev.parent;
0536     int ret;
0537 
0538     /* wake up the rproc before kicking it */
0539     ret = pm_runtime_get_sync(dev);
0540     if (WARN_ON(ret < 0)) {
0541         dev_err(dev, "pm_runtime_get_sync() failed during kick, ret = %d\n",
0542             ret);
0543         pm_runtime_put_noidle(dev);
0544         return;
0545     }
0546 
0547     /* send the index of the triggered virtqueue in the mailbox payload */
0548     ret = mbox_send_message(oproc->mbox, (void *)vqid);
0549     if (ret < 0)
0550         dev_err(dev, "failed to send mailbox message, status = %d\n",
0551             ret);
0552 
0553     pm_runtime_mark_last_busy(dev);
0554     pm_runtime_put_autosuspend(dev);
0555 }
0556 
0557 /**
0558  * omap_rproc_write_dsp_boot_addr() - set boot address for DSP remote processor
0559  * @rproc: handle of a remote processor
0560  *
0561  * Set boot address for a supported DSP remote processor.
0562  *
0563  * Return: 0 on success, or -EINVAL if boot address is not aligned properly
0564  */
0565 static int omap_rproc_write_dsp_boot_addr(struct rproc *rproc)
0566 {
0567     struct device *dev = rproc->dev.parent;
0568     struct omap_rproc *oproc = rproc->priv;
0569     struct omap_rproc_boot_data *bdata = oproc->boot_data;
0570     u32 offset = bdata->boot_reg;
0571     u32 value;
0572     u32 mask;
0573 
0574     if (rproc->bootaddr & (SZ_1K - 1)) {
0575         dev_err(dev, "invalid boot address 0x%llx, must be aligned on a 1KB boundary\n",
0576             rproc->bootaddr);
0577         return -EINVAL;
0578     }
0579 
0580     value = rproc->bootaddr >> bdata->boot_reg_shift;
0581     mask = ~(SZ_1K - 1) >> bdata->boot_reg_shift;
0582 
0583     return regmap_update_bits(bdata->syscon, offset, mask, value);
0584 }
0585 
0586 /*
0587  * Power up the remote processor.
0588  *
0589  * This function will be invoked only after the firmware for this rproc
0590  * was loaded, parsed successfully, and all of its resource requirements
0591  * were met.
0592  */
0593 static int omap_rproc_start(struct rproc *rproc)
0594 {
0595     struct omap_rproc *oproc = rproc->priv;
0596     struct device *dev = rproc->dev.parent;
0597     int ret;
0598     struct mbox_client *client = &oproc->client;
0599 
0600     if (oproc->boot_data) {
0601         ret = omap_rproc_write_dsp_boot_addr(rproc);
0602         if (ret)
0603             return ret;
0604     }
0605 
0606     client->dev = dev;
0607     client->tx_done = NULL;
0608     client->rx_callback = omap_rproc_mbox_callback;
0609     client->tx_block = false;
0610     client->knows_txdone = false;
0611 
0612     oproc->mbox = mbox_request_channel(client, 0);
0613     if (IS_ERR(oproc->mbox)) {
0614         ret = -EBUSY;
0615         dev_err(dev, "mbox_request_channel failed: %ld\n",
0616             PTR_ERR(oproc->mbox));
0617         return ret;
0618     }
0619 
0620     /*
0621      * Ping the remote processor. this is only for sanity-sake;
0622      * there is no functional effect whatsoever.
0623      *
0624      * Note that the reply will _not_ arrive immediately: this message
0625      * will wait in the mailbox fifo until the remote processor is booted.
0626      */
0627     ret = mbox_send_message(oproc->mbox, (void *)RP_MBOX_ECHO_REQUEST);
0628     if (ret < 0) {
0629         dev_err(dev, "mbox_send_message failed: %d\n", ret);
0630         goto put_mbox;
0631     }
0632 
0633     ret = omap_rproc_enable_timers(rproc, true);
0634     if (ret) {
0635         dev_err(dev, "omap_rproc_enable_timers failed: %d\n", ret);
0636         goto put_mbox;
0637     }
0638 
0639     ret = reset_control_deassert(oproc->reset);
0640     if (ret) {
0641         dev_err(dev, "reset control deassert failed: %d\n", ret);
0642         goto disable_timers;
0643     }
0644 
0645     /*
0646      * remote processor is up, so update the runtime pm status and
0647      * enable the auto-suspend. The device usage count is incremented
0648      * manually for balancing it for auto-suspend
0649      */
0650     pm_runtime_set_active(dev);
0651     pm_runtime_use_autosuspend(dev);
0652     pm_runtime_get_noresume(dev);
0653     pm_runtime_enable(dev);
0654     pm_runtime_mark_last_busy(dev);
0655     pm_runtime_put_autosuspend(dev);
0656 
0657     return 0;
0658 
0659 disable_timers:
0660     omap_rproc_disable_timers(rproc, true);
0661 put_mbox:
0662     mbox_free_channel(oproc->mbox);
0663     return ret;
0664 }
0665 
0666 /* power off the remote processor */
0667 static int omap_rproc_stop(struct rproc *rproc)
0668 {
0669     struct device *dev = rproc->dev.parent;
0670     struct omap_rproc *oproc = rproc->priv;
0671     int ret;
0672 
0673     /*
0674      * cancel any possible scheduled runtime suspend by incrementing
0675      * the device usage count, and resuming the device. The remoteproc
0676      * also needs to be woken up if suspended, to avoid the remoteproc
0677      * OS to continue to remember any context that it has saved, and
0678      * avoid potential issues in misindentifying a subsequent device
0679      * reboot as a power restore boot
0680      */
0681     ret = pm_runtime_get_sync(dev);
0682     if (ret < 0) {
0683         pm_runtime_put_noidle(dev);
0684         return ret;
0685     }
0686 
0687     ret = reset_control_assert(oproc->reset);
0688     if (ret)
0689         goto out;
0690 
0691     ret = omap_rproc_disable_timers(rproc, true);
0692     if (ret)
0693         goto enable_device;
0694 
0695     mbox_free_channel(oproc->mbox);
0696 
0697     /*
0698      * update the runtime pm states and status now that the remoteproc
0699      * has stopped
0700      */
0701     pm_runtime_disable(dev);
0702     pm_runtime_dont_use_autosuspend(dev);
0703     pm_runtime_put_noidle(dev);
0704     pm_runtime_set_suspended(dev);
0705 
0706     return 0;
0707 
0708 enable_device:
0709     reset_control_deassert(oproc->reset);
0710 out:
0711     /* schedule the next auto-suspend */
0712     pm_runtime_mark_last_busy(dev);
0713     pm_runtime_put_autosuspend(dev);
0714     return ret;
0715 }
0716 
0717 /**
0718  * omap_rproc_da_to_va() - internal memory translation helper
0719  * @rproc: remote processor to apply the address translation for
0720  * @da: device address to translate
0721  * @len: length of the memory buffer
0722  *
0723  * Custom function implementing the rproc .da_to_va ops to provide address
0724  * translation (device address to kernel virtual address) for internal RAMs
0725  * present in a DSP or IPU device). The translated addresses can be used
0726  * either by the remoteproc core for loading, or by any rpmsg bus drivers.
0727  *
0728  * Return: translated virtual address in kernel memory space on success,
0729  *         or NULL on failure.
0730  */
0731 static void *omap_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
0732 {
0733     struct omap_rproc *oproc = rproc->priv;
0734     int i;
0735     u32 offset;
0736 
0737     if (len <= 0)
0738         return NULL;
0739 
0740     if (!oproc->num_mems)
0741         return NULL;
0742 
0743     for (i = 0; i < oproc->num_mems; i++) {
0744         if (da >= oproc->mem[i].dev_addr && da + len <=
0745             oproc->mem[i].dev_addr + oproc->mem[i].size) {
0746             offset = da - oproc->mem[i].dev_addr;
0747             /* __force to make sparse happy with type conversion */
0748             return (__force void *)(oproc->mem[i].cpu_addr +
0749                         offset);
0750         }
0751     }
0752 
0753     return NULL;
0754 }
0755 
0756 static const struct rproc_ops omap_rproc_ops = {
0757     .start      = omap_rproc_start,
0758     .stop       = omap_rproc_stop,
0759     .kick       = omap_rproc_kick,
0760     .da_to_va   = omap_rproc_da_to_va,
0761 };
0762 
0763 #ifdef CONFIG_PM
0764 static bool _is_rproc_in_standby(struct omap_rproc *oproc)
0765 {
0766     return ti_clk_is_in_standby(oproc->fck);
0767 }
0768 
0769 /* 1 sec is long enough time to let the remoteproc side suspend the device */
0770 #define DEF_SUSPEND_TIMEOUT 1000
0771 static int _omap_rproc_suspend(struct rproc *rproc, bool auto_suspend)
0772 {
0773     struct device *dev = rproc->dev.parent;
0774     struct omap_rproc *oproc = rproc->priv;
0775     unsigned long to = msecs_to_jiffies(DEF_SUSPEND_TIMEOUT);
0776     unsigned long ta = jiffies + to;
0777     u32 suspend_msg = auto_suspend ?
0778                 RP_MBOX_SUSPEND_AUTO : RP_MBOX_SUSPEND_SYSTEM;
0779     int ret;
0780 
0781     reinit_completion(&oproc->pm_comp);
0782     oproc->suspend_acked = false;
0783     ret = mbox_send_message(oproc->mbox, (void *)suspend_msg);
0784     if (ret < 0) {
0785         dev_err(dev, "PM mbox_send_message failed: %d\n", ret);
0786         return ret;
0787     }
0788 
0789     ret = wait_for_completion_timeout(&oproc->pm_comp, to);
0790     if (!oproc->suspend_acked)
0791         return -EBUSY;
0792 
0793     /*
0794      * The remoteproc side is returning the ACK message before saving the
0795      * context, because the context saving is performed within a SYS/BIOS
0796      * function, and it cannot have any inter-dependencies against the IPC
0797      * layer. Also, as the SYS/BIOS needs to preserve properly the processor
0798      * register set, sending this ACK or signalling the completion of the
0799      * context save through a shared memory variable can never be the
0800      * absolute last thing to be executed on the remoteproc side, and the
0801      * MPU cannot use the ACK message as a sync point to put the remoteproc
0802      * into reset. The only way to ensure that the remote processor has
0803      * completed saving the context is to check that the module has reached
0804      * STANDBY state (after saving the context, the SYS/BIOS executes the
0805      * appropriate target-specific WFI instruction causing the module to
0806      * enter STANDBY).
0807      */
0808     while (!_is_rproc_in_standby(oproc)) {
0809         if (time_after(jiffies, ta))
0810             return -ETIME;
0811         schedule();
0812     }
0813 
0814     ret = reset_control_assert(oproc->reset);
0815     if (ret) {
0816         dev_err(dev, "reset assert during suspend failed %d\n", ret);
0817         return ret;
0818     }
0819 
0820     ret = omap_rproc_disable_timers(rproc, false);
0821     if (ret) {
0822         dev_err(dev, "disabling timers during suspend failed %d\n",
0823             ret);
0824         goto enable_device;
0825     }
0826 
0827     /*
0828      * IOMMUs would have to be disabled specifically for runtime suspend.
0829      * They are handled automatically through System PM callbacks for
0830      * regular system suspend
0831      */
0832     if (auto_suspend) {
0833         ret = omap_iommu_domain_deactivate(rproc->domain);
0834         if (ret) {
0835             dev_err(dev, "iommu domain deactivate failed %d\n",
0836                 ret);
0837             goto enable_timers;
0838         }
0839     }
0840 
0841     return 0;
0842 
0843 enable_timers:
0844     /* ignore errors on re-enabling code */
0845     omap_rproc_enable_timers(rproc, false);
0846 enable_device:
0847     reset_control_deassert(oproc->reset);
0848     return ret;
0849 }
0850 
0851 static int _omap_rproc_resume(struct rproc *rproc, bool auto_suspend)
0852 {
0853     struct device *dev = rproc->dev.parent;
0854     struct omap_rproc *oproc = rproc->priv;
0855     int ret;
0856 
0857     /*
0858      * IOMMUs would have to be enabled specifically for runtime resume.
0859      * They would have been already enabled automatically through System
0860      * PM callbacks for regular system resume
0861      */
0862     if (auto_suspend) {
0863         ret = omap_iommu_domain_activate(rproc->domain);
0864         if (ret) {
0865             dev_err(dev, "omap_iommu activate failed %d\n", ret);
0866             goto out;
0867         }
0868     }
0869 
0870     /* boot address could be lost after suspend, so restore it */
0871     if (oproc->boot_data) {
0872         ret = omap_rproc_write_dsp_boot_addr(rproc);
0873         if (ret) {
0874             dev_err(dev, "boot address restore failed %d\n", ret);
0875             goto suspend_iommu;
0876         }
0877     }
0878 
0879     ret = omap_rproc_enable_timers(rproc, false);
0880     if (ret) {
0881         dev_err(dev, "enabling timers during resume failed %d\n", ret);
0882         goto suspend_iommu;
0883     }
0884 
0885     ret = reset_control_deassert(oproc->reset);
0886     if (ret) {
0887         dev_err(dev, "reset deassert during resume failed %d\n", ret);
0888         goto disable_timers;
0889     }
0890 
0891     return 0;
0892 
0893 disable_timers:
0894     omap_rproc_disable_timers(rproc, false);
0895 suspend_iommu:
0896     if (auto_suspend)
0897         omap_iommu_domain_deactivate(rproc->domain);
0898 out:
0899     return ret;
0900 }
0901 
0902 static int __maybe_unused omap_rproc_suspend(struct device *dev)
0903 {
0904     struct rproc *rproc = dev_get_drvdata(dev);
0905     struct omap_rproc *oproc = rproc->priv;
0906     int ret = 0;
0907 
0908     mutex_lock(&rproc->lock);
0909     if (rproc->state == RPROC_OFFLINE)
0910         goto out;
0911 
0912     if (rproc->state == RPROC_SUSPENDED)
0913         goto out;
0914 
0915     if (rproc->state != RPROC_RUNNING) {
0916         ret = -EBUSY;
0917         goto out;
0918     }
0919 
0920     ret = _omap_rproc_suspend(rproc, false);
0921     if (ret) {
0922         dev_err(dev, "suspend failed %d\n", ret);
0923         goto out;
0924     }
0925 
0926     /*
0927      * remoteproc is running at the time of system suspend, so remember
0928      * it so as to wake it up during system resume
0929      */
0930     oproc->need_resume = true;
0931     rproc->state = RPROC_SUSPENDED;
0932 
0933 out:
0934     mutex_unlock(&rproc->lock);
0935     return ret;
0936 }
0937 
0938 static int __maybe_unused omap_rproc_resume(struct device *dev)
0939 {
0940     struct rproc *rproc = dev_get_drvdata(dev);
0941     struct omap_rproc *oproc = rproc->priv;
0942     int ret = 0;
0943 
0944     mutex_lock(&rproc->lock);
0945     if (rproc->state == RPROC_OFFLINE)
0946         goto out;
0947 
0948     if (rproc->state != RPROC_SUSPENDED) {
0949         ret = -EBUSY;
0950         goto out;
0951     }
0952 
0953     /*
0954      * remoteproc was auto-suspended at the time of system suspend,
0955      * so no need to wake-up the processor (leave it in suspended
0956      * state, will be woken up during a subsequent runtime_resume)
0957      */
0958     if (!oproc->need_resume)
0959         goto out;
0960 
0961     ret = _omap_rproc_resume(rproc, false);
0962     if (ret) {
0963         dev_err(dev, "resume failed %d\n", ret);
0964         goto out;
0965     }
0966 
0967     oproc->need_resume = false;
0968     rproc->state = RPROC_RUNNING;
0969 
0970     pm_runtime_mark_last_busy(dev);
0971 out:
0972     mutex_unlock(&rproc->lock);
0973     return ret;
0974 }
0975 
0976 static int omap_rproc_runtime_suspend(struct device *dev)
0977 {
0978     struct rproc *rproc = dev_get_drvdata(dev);
0979     struct omap_rproc *oproc = rproc->priv;
0980     int ret;
0981 
0982     mutex_lock(&rproc->lock);
0983     if (rproc->state == RPROC_CRASHED) {
0984         dev_dbg(dev, "rproc cannot be runtime suspended when crashed!\n");
0985         ret = -EBUSY;
0986         goto out;
0987     }
0988 
0989     if (WARN_ON(rproc->state != RPROC_RUNNING)) {
0990         dev_err(dev, "rproc cannot be runtime suspended when not running!\n");
0991         ret = -EBUSY;
0992         goto out;
0993     }
0994 
0995     /*
0996      * do not even attempt suspend if the remote processor is not
0997      * idled for runtime auto-suspend
0998      */
0999     if (!_is_rproc_in_standby(oproc)) {
1000         ret = -EBUSY;
1001         goto abort;
1002     }
1003 
1004     ret = _omap_rproc_suspend(rproc, true);
1005     if (ret)
1006         goto abort;
1007 
1008     rproc->state = RPROC_SUSPENDED;
1009     mutex_unlock(&rproc->lock);
1010     return 0;
1011 
1012 abort:
1013     pm_runtime_mark_last_busy(dev);
1014 out:
1015     mutex_unlock(&rproc->lock);
1016     return ret;
1017 }
1018 
1019 static int omap_rproc_runtime_resume(struct device *dev)
1020 {
1021     struct rproc *rproc = dev_get_drvdata(dev);
1022     int ret;
1023 
1024     mutex_lock(&rproc->lock);
1025     if (WARN_ON(rproc->state != RPROC_SUSPENDED)) {
1026         dev_err(dev, "rproc cannot be runtime resumed if not suspended! state=%d\n",
1027             rproc->state);
1028         ret = -EBUSY;
1029         goto out;
1030     }
1031 
1032     ret = _omap_rproc_resume(rproc, true);
1033     if (ret) {
1034         dev_err(dev, "runtime resume failed %d\n", ret);
1035         goto out;
1036     }
1037 
1038     rproc->state = RPROC_RUNNING;
1039 out:
1040     mutex_unlock(&rproc->lock);
1041     return ret;
1042 }
1043 #endif /* CONFIG_PM */
1044 
1045 static const struct omap_rproc_mem_data ipu_mems[] = {
1046     { .name = "l2ram", .dev_addr = 0x20000000 },
1047     { },
1048 };
1049 
1050 static const struct omap_rproc_mem_data dra7_dsp_mems[] = {
1051     { .name = "l2ram", .dev_addr = 0x800000 },
1052     { .name = "l1pram", .dev_addr = 0xe00000 },
1053     { .name = "l1dram", .dev_addr = 0xf00000 },
1054     { },
1055 };
1056 
1057 static const struct omap_rproc_dev_data omap4_dsp_dev_data = {
1058     .device_name    = "dsp",
1059 };
1060 
1061 static const struct omap_rproc_dev_data omap4_ipu_dev_data = {
1062     .device_name    = "ipu",
1063     .mems       = ipu_mems,
1064 };
1065 
1066 static const struct omap_rproc_dev_data omap5_dsp_dev_data = {
1067     .device_name    = "dsp",
1068 };
1069 
1070 static const struct omap_rproc_dev_data omap5_ipu_dev_data = {
1071     .device_name    = "ipu",
1072     .mems       = ipu_mems,
1073 };
1074 
1075 static const struct omap_rproc_dev_data dra7_dsp_dev_data = {
1076     .device_name    = "dsp",
1077     .mems       = dra7_dsp_mems,
1078 };
1079 
1080 static const struct omap_rproc_dev_data dra7_ipu_dev_data = {
1081     .device_name    = "ipu",
1082     .mems       = ipu_mems,
1083 };
1084 
1085 static const struct of_device_id omap_rproc_of_match[] = {
1086     {
1087         .compatible     = "ti,omap4-dsp",
1088         .data           = &omap4_dsp_dev_data,
1089     },
1090     {
1091         .compatible     = "ti,omap4-ipu",
1092         .data           = &omap4_ipu_dev_data,
1093     },
1094     {
1095         .compatible     = "ti,omap5-dsp",
1096         .data           = &omap5_dsp_dev_data,
1097     },
1098     {
1099         .compatible     = "ti,omap5-ipu",
1100         .data           = &omap5_ipu_dev_data,
1101     },
1102     {
1103         .compatible     = "ti,dra7-dsp",
1104         .data           = &dra7_dsp_dev_data,
1105     },
1106     {
1107         .compatible     = "ti,dra7-ipu",
1108         .data           = &dra7_ipu_dev_data,
1109     },
1110     {
1111         /* end */
1112     },
1113 };
1114 MODULE_DEVICE_TABLE(of, omap_rproc_of_match);
1115 
1116 static const char *omap_rproc_get_firmware(struct platform_device *pdev)
1117 {
1118     const char *fw_name;
1119     int ret;
1120 
1121     ret = of_property_read_string(pdev->dev.of_node, "firmware-name",
1122                       &fw_name);
1123     if (ret)
1124         return ERR_PTR(ret);
1125 
1126     return fw_name;
1127 }
1128 
1129 static int omap_rproc_get_boot_data(struct platform_device *pdev,
1130                     struct rproc *rproc)
1131 {
1132     struct device_node *np = pdev->dev.of_node;
1133     struct omap_rproc *oproc = rproc->priv;
1134     const struct omap_rproc_dev_data *data;
1135     int ret;
1136 
1137     data = of_device_get_match_data(&pdev->dev);
1138     if (!data)
1139         return -ENODEV;
1140 
1141     if (!of_property_read_bool(np, "ti,bootreg"))
1142         return 0;
1143 
1144     oproc->boot_data = devm_kzalloc(&pdev->dev, sizeof(*oproc->boot_data),
1145                     GFP_KERNEL);
1146     if (!oproc->boot_data)
1147         return -ENOMEM;
1148 
1149     oproc->boot_data->syscon =
1150             syscon_regmap_lookup_by_phandle(np, "ti,bootreg");
1151     if (IS_ERR(oproc->boot_data->syscon)) {
1152         ret = PTR_ERR(oproc->boot_data->syscon);
1153         return ret;
1154     }
1155 
1156     if (of_property_read_u32_index(np, "ti,bootreg", 1,
1157                        &oproc->boot_data->boot_reg)) {
1158         dev_err(&pdev->dev, "couldn't get the boot register\n");
1159         return -EINVAL;
1160     }
1161 
1162     of_property_read_u32_index(np, "ti,bootreg", 2,
1163                    &oproc->boot_data->boot_reg_shift);
1164 
1165     return 0;
1166 }
1167 
1168 static int omap_rproc_of_get_internal_memories(struct platform_device *pdev,
1169                            struct rproc *rproc)
1170 {
1171     struct omap_rproc *oproc = rproc->priv;
1172     struct device *dev = &pdev->dev;
1173     const struct omap_rproc_dev_data *data;
1174     struct resource *res;
1175     int num_mems;
1176     int i;
1177 
1178     data = of_device_get_match_data(dev);
1179     if (!data)
1180         return -ENODEV;
1181 
1182     if (!data->mems)
1183         return 0;
1184 
1185     num_mems = of_property_count_elems_of_size(dev->of_node, "reg",
1186                            sizeof(u32)) / 2;
1187 
1188     oproc->mem = devm_kcalloc(dev, num_mems, sizeof(*oproc->mem),
1189                   GFP_KERNEL);
1190     if (!oproc->mem)
1191         return -ENOMEM;
1192 
1193     for (i = 0; data->mems[i].name; i++) {
1194         res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1195                            data->mems[i].name);
1196         if (!res) {
1197             dev_err(dev, "no memory defined for %s\n",
1198                 data->mems[i].name);
1199             return -ENOMEM;
1200         }
1201         oproc->mem[i].cpu_addr = devm_ioremap_resource(dev, res);
1202         if (IS_ERR(oproc->mem[i].cpu_addr)) {
1203             dev_err(dev, "failed to parse and map %s memory\n",
1204                 data->mems[i].name);
1205             return PTR_ERR(oproc->mem[i].cpu_addr);
1206         }
1207         oproc->mem[i].bus_addr = res->start;
1208         oproc->mem[i].dev_addr = data->mems[i].dev_addr;
1209         oproc->mem[i].size = resource_size(res);
1210 
1211         dev_dbg(dev, "memory %8s: bus addr %pa size 0x%x va %pK da 0x%x\n",
1212             data->mems[i].name, &oproc->mem[i].bus_addr,
1213             oproc->mem[i].size, oproc->mem[i].cpu_addr,
1214             oproc->mem[i].dev_addr);
1215     }
1216     oproc->num_mems = num_mems;
1217 
1218     return 0;
1219 }
1220 
1221 #ifdef CONFIG_OMAP_REMOTEPROC_WATCHDOG
1222 static int omap_rproc_count_wdog_timers(struct device *dev)
1223 {
1224     struct device_node *np = dev->of_node;
1225     int ret;
1226 
1227     ret = of_count_phandle_with_args(np, "ti,watchdog-timers", NULL);
1228     if (ret <= 0) {
1229         dev_dbg(dev, "device does not have watchdog timers, status = %d\n",
1230             ret);
1231         ret = 0;
1232     }
1233 
1234     return ret;
1235 }
1236 #else
1237 static int omap_rproc_count_wdog_timers(struct device *dev)
1238 {
1239     return 0;
1240 }
1241 #endif
1242 
1243 static int omap_rproc_of_get_timers(struct platform_device *pdev,
1244                     struct rproc *rproc)
1245 {
1246     struct device_node *np = pdev->dev.of_node;
1247     struct omap_rproc *oproc = rproc->priv;
1248     struct device *dev = &pdev->dev;
1249     int num_timers;
1250 
1251     /*
1252      * Timer nodes are directly used in client nodes as phandles, so
1253      * retrieve the count using appropriate size
1254      */
1255     oproc->num_timers = of_count_phandle_with_args(np, "ti,timers", NULL);
1256     if (oproc->num_timers <= 0) {
1257         dev_dbg(dev, "device does not have timers, status = %d\n",
1258             oproc->num_timers);
1259         oproc->num_timers = 0;
1260     }
1261 
1262     oproc->num_wd_timers = omap_rproc_count_wdog_timers(dev);
1263 
1264     num_timers = oproc->num_timers + oproc->num_wd_timers;
1265     if (num_timers) {
1266         oproc->timers = devm_kcalloc(dev, num_timers,
1267                          sizeof(*oproc->timers),
1268                          GFP_KERNEL);
1269         if (!oproc->timers)
1270             return -ENOMEM;
1271 
1272         dev_dbg(dev, "device has %d tick timers and %d watchdog timers\n",
1273             oproc->num_timers, oproc->num_wd_timers);
1274     }
1275 
1276     return 0;
1277 }
1278 
1279 static int omap_rproc_probe(struct platform_device *pdev)
1280 {
1281     struct device_node *np = pdev->dev.of_node;
1282     struct omap_rproc *oproc;
1283     struct rproc *rproc;
1284     const char *firmware;
1285     int ret;
1286     struct reset_control *reset;
1287 
1288     if (!np) {
1289         dev_err(&pdev->dev, "only DT-based devices are supported\n");
1290         return -ENODEV;
1291     }
1292 
1293     reset = devm_reset_control_array_get_exclusive(&pdev->dev);
1294     if (IS_ERR(reset))
1295         return PTR_ERR(reset);
1296 
1297     firmware = omap_rproc_get_firmware(pdev);
1298     if (IS_ERR(firmware))
1299         return PTR_ERR(firmware);
1300 
1301     ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
1302     if (ret) {
1303         dev_err(&pdev->dev, "dma_set_coherent_mask: %d\n", ret);
1304         return ret;
1305     }
1306 
1307     rproc = rproc_alloc(&pdev->dev, dev_name(&pdev->dev), &omap_rproc_ops,
1308                 firmware, sizeof(*oproc));
1309     if (!rproc)
1310         return -ENOMEM;
1311 
1312     oproc = rproc->priv;
1313     oproc->rproc = rproc;
1314     oproc->reset = reset;
1315     /* All existing OMAP IPU and DSP processors have an MMU */
1316     rproc->has_iommu = true;
1317 
1318     ret = omap_rproc_of_get_internal_memories(pdev, rproc);
1319     if (ret)
1320         goto free_rproc;
1321 
1322     ret = omap_rproc_get_boot_data(pdev, rproc);
1323     if (ret)
1324         goto free_rproc;
1325 
1326     ret = omap_rproc_of_get_timers(pdev, rproc);
1327     if (ret)
1328         goto free_rproc;
1329 
1330     init_completion(&oproc->pm_comp);
1331     oproc->autosuspend_delay = DEFAULT_AUTOSUSPEND_DELAY;
1332 
1333     of_property_read_u32(pdev->dev.of_node, "ti,autosuspend-delay-ms",
1334                  &oproc->autosuspend_delay);
1335 
1336     pm_runtime_set_autosuspend_delay(&pdev->dev, oproc->autosuspend_delay);
1337 
1338     oproc->fck = devm_clk_get(&pdev->dev, 0);
1339     if (IS_ERR(oproc->fck)) {
1340         ret = PTR_ERR(oproc->fck);
1341         goto free_rproc;
1342     }
1343 
1344     ret = of_reserved_mem_device_init(&pdev->dev);
1345     if (ret) {
1346         dev_warn(&pdev->dev, "device does not have specific CMA pool.\n");
1347         dev_warn(&pdev->dev, "Typically this should be provided,\n");
1348         dev_warn(&pdev->dev, "only omit if you know what you are doing.\n");
1349     }
1350 
1351     platform_set_drvdata(pdev, rproc);
1352 
1353     ret = rproc_add(rproc);
1354     if (ret)
1355         goto release_mem;
1356 
1357     return 0;
1358 
1359 release_mem:
1360     of_reserved_mem_device_release(&pdev->dev);
1361 free_rproc:
1362     rproc_free(rproc);
1363     return ret;
1364 }
1365 
1366 static int omap_rproc_remove(struct platform_device *pdev)
1367 {
1368     struct rproc *rproc = platform_get_drvdata(pdev);
1369 
1370     rproc_del(rproc);
1371     rproc_free(rproc);
1372     of_reserved_mem_device_release(&pdev->dev);
1373 
1374     return 0;
1375 }
1376 
1377 static const struct dev_pm_ops omap_rproc_pm_ops = {
1378     SET_SYSTEM_SLEEP_PM_OPS(omap_rproc_suspend, omap_rproc_resume)
1379     SET_RUNTIME_PM_OPS(omap_rproc_runtime_suspend,
1380                omap_rproc_runtime_resume, NULL)
1381 };
1382 
1383 static struct platform_driver omap_rproc_driver = {
1384     .probe = omap_rproc_probe,
1385     .remove = omap_rproc_remove,
1386     .driver = {
1387         .name = "omap-rproc",
1388         .pm = &omap_rproc_pm_ops,
1389         .of_match_table = omap_rproc_of_match,
1390     },
1391 };
1392 
1393 module_platform_driver(omap_rproc_driver);
1394 
1395 MODULE_LICENSE("GPL v2");
1396 MODULE_DESCRIPTION("OMAP Remote Processor control driver");