drivers/remoteproc/meson_mx_ao_arc.c

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

File Facts

System
Linux kernel
Corpus path
drivers/remoteproc/meson_mx_ao_arc.c
Extension
.c
Size
7307 bytes
Lines
260
Domain
Driver Families
Bucket
drivers/remoteproc
Inferred role
Driver Families: implementation source
Status
source 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

struct meson_mx_ao_arc_rproc_priv {
	void __iomem		*remap_base;
	void __iomem		*cpu_base;
	unsigned long		sram_va;
	phys_addr_t		sram_pa;
	size_t			sram_size;
	struct gen_pool		*sram_pool;
	struct reset_control	*arc_reset;
	struct clk		*arc_pclk;
	struct regmap		*secbus2_regmap;
};

static int meson_mx_ao_arc_rproc_start(struct rproc *rproc)
{
	struct meson_mx_ao_arc_rproc_priv *priv = rproc->priv;
	phys_addr_t translated_sram_addr;
	u32 tmp;
	int ret;

	ret = clk_prepare_enable(priv->arc_pclk);
	if (ret)
		return ret;

	tmp = FIELD_PREP(AO_REMAP_REG0_REMAP_AHB_SRAM_BITS_17_14_FOR_ARM_CPU,
			 priv->sram_pa >> 14);
	writel(tmp, priv->remap_base + AO_REMAP_REG0);

	/*
	 * The SRAM content as seen by the ARC core always starts at 0x0
	 * regardless of the value given here (this was discovered by trial and
	 * error). For SoCs older than Meson6 we probably have to set
	 * AO_REMAP_REG1_MOVE_AHB_SRAM_TO_0X0_INSTEAD_OF_DDR to achieve the
	 * same. (At least) For Meson8 and newer that bit must not be set.
	 */
	writel(0x0, priv->remap_base + AO_REMAP_REG1);

	regmap_update_bits(priv->secbus2_regmap, AO_SECURE_REG0,
			   AO_SECURE_REG0_AHB_SRAM_BITS_19_12,
			   FIELD_PREP(AO_SECURE_REG0_AHB_SRAM_BITS_19_12,
				      priv->sram_pa >> 12));

	ret = reset_control_reset(priv->arc_reset);
	if (ret) {
		clk_disable_unprepare(priv->arc_pclk);
		return ret;
	}

	usleep_range(10, 100);

	/*
	 * Convert from 0xd9000000 to 0xc9000000 as the vendor driver does.
	 * This only seems to be relevant for the AO_CPU_CNTL register. It is
	 * unknown why this is needed.
	 */
	translated_sram_addr = priv->sram_pa - MESON_AO_RPROC_MEMORY_OFFSET;

	tmp = FIELD_PREP(AO_CPU_CNTL_AHB_SRAM_BITS_31_20,
			 translated_sram_addr >> 20);
	tmp |= AO_CPU_CNTL_UNKNONWN | AO_CPU_CNTL_RUN;
	writel(tmp, priv->cpu_base + AO_CPU_CNTL);

	usleep_range(20, 200);

	return 0;
}

static int meson_mx_ao_arc_rproc_stop(struct rproc *rproc)
{
	struct meson_mx_ao_arc_rproc_priv *priv = rproc->priv;

	writel(AO_CPU_CNTL_HALT, priv->cpu_base + AO_CPU_CNTL);

	clk_disable_unprepare(priv->arc_pclk);

	return 0;
}

static void *meson_mx_ao_arc_rproc_da_to_va(struct rproc *rproc, u64 da,
					    size_t len, bool *is_iomem)
{
	struct meson_mx_ao_arc_rproc_priv *priv = rproc->priv;

	/* The memory from the ARC core's perspective always starts at 0x0. */
	if ((da + len) > priv->sram_size)
		return NULL;

	return (void *)priv->sram_va + da;
}

static struct rproc_ops meson_mx_ao_arc_rproc_ops = {

Annotation

Implementation Notes