drivers/media/platform/renesas/rzv2h-ivc/rzv2h-ivc-dev.c

Source file repositories/reference/linux-study-clean/drivers/media/platform/renesas/rzv2h-ivc/rzv2h-ivc-dev.c

File Facts

System
Linux kernel
Corpus path
drivers/media/platform/renesas/rzv2h-ivc/rzv2h-ivc-dev.c
Extension
.c
Size
6122 bytes
Lines
252
Domain
Driver Families
Bucket
drivers/media
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

// SPDX-License-Identifier: GPL-2.0
/*
 * Renesas RZ/V2H(P) Input Video Control Block driver
 *
 * Copyright (C) 2025 Ideas on Board Oy
 */

#include "rzv2h-ivc.h"

#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>

void rzv2h_ivc_write(struct rzv2h_ivc *ivc, u32 addr, u32 val)
{
	writel(val, ivc->base + addr);
}

void rzv2h_ivc_update_bits(struct rzv2h_ivc *ivc, unsigned int addr,
			   u32 mask, u32 val)
{
	u32 orig, new;

	orig = readl(ivc->base + addr);

	new = orig & ~mask;
	new |= val & mask;

	if (new != orig)
		writel(new, ivc->base + addr);
}

static int rzv2h_ivc_get_hardware_resources(struct rzv2h_ivc *ivc,
					    struct platform_device *pdev)
{
	static const char * const resource_names[RZV2H_IVC_NUM_HW_RESOURCES] = {
		"reg",
		"axi",
		"isp",
	};
	struct resource *res;
	int ret;

	ivc->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
	if (IS_ERR(ivc->base))
		return dev_err_probe(ivc->dev, PTR_ERR(ivc->base),
				     "failed to map IO memory\n");

	for (unsigned int i = 0; i < ARRAY_SIZE(resource_names); i++)
		ivc->clks[i].id = resource_names[i];

	ret = devm_clk_bulk_get(ivc->dev, ARRAY_SIZE(resource_names), ivc->clks);
	if (ret)
		return dev_err_probe(ivc->dev, ret, "failed to acquire clks\n");

	for (unsigned int i = 0; i < ARRAY_SIZE(resource_names); i++)
		ivc->resets[i].id = resource_names[i];

	ret = devm_reset_control_bulk_get_optional_shared(ivc->dev,
						ARRAY_SIZE(resource_names),
						ivc->resets);
	if (ret)
		return dev_err_probe(ivc->dev, ret, "failed to acquire resets\n");

	return 0;
}

static void rzv2h_ivc_global_config(struct rzv2h_ivc *ivc)
{
	/* Currently we only support single-exposure input */
	rzv2h_ivc_write(ivc, RZV2H_IVC_REG_AXIRX_PLNUM, RZV2H_IVC_ONE_EXPOSURE);

	/*
	 * Datasheet says we should disable the interrupts before changing mode
	 * to avoid spurious IFP interrupt.
	 */
	rzv2h_ivc_write(ivc, RZV2H_IVC_REG_FM_INT_EN, 0x0);

	/*
	 * RZ/V2H(P) documentation says software controlled single context mode
	 * is not supported, and currently the driver does not support the
	 * multi-context mode. That being so we just set single context sw-hw
	 * mode.
	 */
	rzv2h_ivc_write(ivc, RZV2H_IVC_REG_FM_CONTEXT,
			RZV2H_IVC_SINGLE_CONTEXT_SW_HW_CFG);

Annotation

Implementation Notes