drivers/remoteproc/qcom_q6v5.c

Source file repositories/reference/linux-study-clean/drivers/remoteproc/qcom_q6v5.c

File Facts

System
Linux kernel
Corpus path
drivers/remoteproc/qcom_q6v5.c
Extension
.c
Size
9663 bytes
Lines
370
Domain
Driver Families
Bucket
drivers/remoteproc
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0
/*
 * Qualcomm Peripheral Image Loader for Q6V5
 *
 * Copyright (C) 2016-2018 Linaro Ltd.
 * Copyright (C) 2014 Sony Mobile Communications AB
 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
 */
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/interconnect.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/soc/qcom/qcom_aoss.h>
#include <linux/soc/qcom/smem.h>
#include <linux/soc/qcom/smem_state.h>
#include <linux/remoteproc.h>
#include "qcom_common.h"
#include "qcom_q6v5.h"

#define Q6V5_LOAD_STATE_MSG_LEN	64
#define Q6V5_PANIC_DELAY_MS	200

static int q6v5_load_state_toggle(struct qcom_q6v5 *q6v5, bool enable)
{
	int ret;

	if (!q6v5->qmp)
		return 0;

	ret = qmp_send(q6v5->qmp, "{class: image, res: load_state, name: %s, val: %s}",
		       q6v5->load_state, enable ? "on" : "off");
	if (ret)
		dev_err(q6v5->dev, "failed to toggle load state\n");

	return ret;
}

/**
 * qcom_q6v5_prepare() - reinitialize the qcom_q6v5 context before start
 * @q6v5:	reference to qcom_q6v5 context to be reinitialized
 *
 * Return: 0 on success, negative errno on failure
 */
int qcom_q6v5_prepare(struct qcom_q6v5 *q6v5)
{
	int ret;

	ret = icc_set_bw(q6v5->path, 0, UINT_MAX);
	if (ret < 0) {
		dev_err(q6v5->dev, "failed to set bandwidth request\n");
		return ret;
	}

	ret = q6v5_load_state_toggle(q6v5, true);
	if (ret) {
		icc_set_bw(q6v5->path, 0, 0);
		return ret;
	}

	reinit_completion(&q6v5->start_done);
	reinit_completion(&q6v5->stop_done);

	q6v5->running = true;
	q6v5->handover_issued = false;

	enable_irq(q6v5->handover_irq);

	return 0;
}
EXPORT_SYMBOL_GPL(qcom_q6v5_prepare);

/**
 * qcom_q6v5_unprepare() - unprepare the qcom_q6v5 context after stop
 * @q6v5:	reference to qcom_q6v5 context to be unprepared
 *
 * Return: 0 on success, 1 if handover hasn't yet been called
 */
int qcom_q6v5_unprepare(struct qcom_q6v5 *q6v5)
{
	disable_irq(q6v5->handover_irq);
	q6v5_load_state_toggle(q6v5, false);

	/* Disable interconnect vote, in case handover never happened */
	icc_set_bw(q6v5->path, 0, 0);

	return !q6v5->handover_issued;
}
EXPORT_SYMBOL_GPL(qcom_q6v5_unprepare);

Annotation

Implementation Notes