/** * wkup_m3_copy_aux_data - Copy auxiliary data to special region of m3 dmem * @data - pointer to data * @sz - size of data to copy (limit 256 bytes) * * Copies any additional blob of data to the wkup_m3 dmem to be used by the * firmware
*/ staticunsignedlong wkup_m3_copy_aux_data(struct wkup_m3_ipc *m3_ipc, constvoid *data, int sz)
{ unsignedlong aux_data_dev_addr; void *aux_data_addr;
if (!m3_ipc->mbox) {
dev_err(dev, "No IPC channel to communicate with wkup_m3!\n"); return -EIO;
}
/* * Write a dummy message to the mailbox in order to trigger the RX * interrupt to alert the M3 that data is available in the IPC * registers. We must enable the IRQ here and disable it after in * the RX callback to avoid multiple interrupts being received * by the CM3.
*/
ret = mbox_send_message(m3_ipc->mbox, NULL); if (ret < 0) {
dev_err(dev, "%s: mbox_send_message() failed: %d\n",
__func__, ret); return ret;
}
ret = wait_for_completion_timeout(&m3_ipc->sync_complete,
msecs_to_jiffies(500)); if (!ret) {
dev_err(dev, "MPU<->CM3 sync failure\n");
m3_ipc->state = M3_STATE_UNKNOWN; return -EIO;
}
/* Public functions */ /** * wkup_m3_set_mem_type - Pass wkup_m3 which type of memory is in use * @m3_ipc: Pointer to wkup_m3_ipc context * @mem_type: memory type value read directly from emif * * wkup_m3 must know what memory type is in use to properly suspend * and resume.
*/ staticvoid wkup_m3_set_mem_type(struct wkup_m3_ipc *m3_ipc, int mem_type)
{
m3_ipc->mem_type = mem_type;
}
/** * wkup_m3_set_resume_address - Pass wkup_m3 resume address * @m3_ipc: Pointer to wkup_m3_ipc context * @addr: Physical address from which resume code should execute
*/ staticvoid wkup_m3_set_resume_address(struct wkup_m3_ipc *m3_ipc, void *addr)
{
m3_ipc->resume_addr = (unsignedlong)addr;
}
/** * wkup_m3_request_pm_status - Retrieve wkup_m3 status code after suspend * @m3_ipc: Pointer to wkup_m3_ipc context * * Returns code representing the status of a low power mode transition. * 0 - Successful transition * 1 - Failure to transition to low power state
*/ staticint wkup_m3_request_pm_status(struct wkup_m3_ipc *m3_ipc)
{ unsignedint i; int val;
val = wkup_m3_ctrl_ipc_read(m3_ipc, 1);
i = M3_STATUS_RESP_MASK & val;
i >>= __ffs(M3_STATUS_RESP_MASK);
return i;
}
/** * wkup_m3_prepare_low_power - Request preparation for transition to * low power state * @m3_ipc: Pointer to wkup_m3_ipc context * @state: A kernel suspend state to enter, either MEM or STANDBY * * Returns 0 if preparation was successful, otherwise returns error code
*/ staticint wkup_m3_prepare_low_power(struct wkup_m3_ipc *m3_ipc, int state)
{ struct device *dev = m3_ipc->dev; int m3_power_state; int ret = 0;
if (!wkup_m3_is_available(m3_ipc)) return -ENODEV;
ret = wkup_m3_ping(m3_ipc); if (ret) {
dev_err(dev, "Unable to ping CM3\n"); return ret;
}
return 0;
}
/** * wkup_m3_request_wake_src - Get the wakeup source info passed from wkup_m3 * @m3_ipc: Pointer to wkup_m3_ipc context
*/ staticconstchar *wkup_m3_request_wake_src(struct wkup_m3_ipc *m3_ipc)
{ unsignedint wakeup_src_idx; int j, val;
/** * wkup_m3_ipc_put - Free handle to wkup_m3_ipc returned from wkup_m3_ipc_get * @m3_ipc: A pointer to wkup_m3_ipc struct returned by wkup_m3_ipc_get
*/ void wkup_m3_ipc_put(struct wkup_m3_ipc *m3_ipc)
{ if (m3_ipc_state)
put_device(m3_ipc_state->dev);
}
EXPORT_SYMBOL_GPL(wkup_m3_ipc_put);
if (IS_ERR(m3_ipc->mbox)) return dev_err_probe(dev, PTR_ERR(m3_ipc->mbox), "IPC Request for A8->M3 Channel failed!\n");
if (of_property_read_u32(dev->of_node, "ti,rproc", &rproc_phandle)) {
dev_err(&pdev->dev, "could not get rproc phandle\n");
ret = -ENODEV; goto err_free_mbox;
}
m3_rproc = rproc_get_by_phandle(rproc_phandle); if (!m3_rproc) {
dev_err(&pdev->dev, "could not get rproc handle\n");
ret = -EPROBE_DEFER; goto err_free_mbox;
}
if (of_property_read_bool(np, "ti,set-io-isolation"))
wkup_m3_set_io_isolation(m3_ipc);
ret = of_property_read_string(np, "firmware-name",
&m3_ipc->sd_fw_name); if (ret) {
dev_dbg(dev, "Voltage scaling data blob not provided from DT.\n");
}
/* * Wait for firmware loading completion in a thread so we * can boot the wkup_m3 as soon as it's ready without holding * up kernel boot
*/
task = kthread_run(wkup_m3_rproc_boot_thread, m3_ipc, "wkup_m3_rproc_loader");
if (IS_ERR(task)) {
dev_err(dev, "can't create rproc_boot thread\n");
ret = PTR_ERR(task); goto err_put_rproc;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.