File Index
Files and directories
Sign in
FILE

rocket_core.c

File preview with syntax highlighting.

linux-6.19.14/drivers/accel/rocket/rocket_core.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/* Copyright 2024-2025 Tomeu Vizoso <tomeu@tomeuvizoso.net> */
  3
  4#include <linux/clk.h>
  5#include <linux/delay.h>
  6#include <linux/dev_printk.h>
  7#include <linux/dma-mapping.h>
  8#include <linux/err.h>
  9#include <linux/iommu.h>
 10#include <linux/platform_device.h>
 11#include <linux/pm_runtime.h>
 12#include <linux/reset.h>
 13
 14#include "rocket_core.h"
 15#include "rocket_job.h"
 16
 17int rocket_core_init(struct rocket_core *core)
 18{
 19	struct device *dev = core->dev;
 20	struct platform_device *pdev = to_platform_device(dev);
 21	u32 version;
 22	int err = 0;
 23
 24	core->resets[0].id = "srst_a";
 25	core->resets[1].id = "srst_h";
 26	err = devm_reset_control_bulk_get_exclusive(&pdev->dev, ARRAY_SIZE(core->resets),
 27						    core->resets);
 28	if (err)
 29		return dev_err_probe(dev, err, "failed to get resets for core %d\n", core->index);
 30
 31	err = devm_clk_bulk_get(dev, ARRAY_SIZE(core->clks), core->clks);
 32	if (err)
 33		return dev_err_probe(dev, err, "failed to get clocks for core %d\n", core->index);
 34
 35	core->pc_iomem = devm_platform_ioremap_resource_byname(pdev, "pc");
 36	if (IS_ERR(core->pc_iomem)) {
 37		dev_err(dev, "couldn't find PC registers %ld\n", PTR_ERR(core->pc_iomem));
 38		return PTR_ERR(core->pc_iomem);
 39	}
 40
 41	core->cna_iomem = devm_platform_ioremap_resource_byname(pdev, "cna");
 42	if (IS_ERR(core->cna_iomem)) {
 43		dev_err(dev, "couldn't find CNA registers %ld\n", PTR_ERR(core->cna_iomem));
 44		return PTR_ERR(core->cna_iomem);
 45	}
 46
 47	core->core_iomem = devm_platform_ioremap_resource_byname(pdev, "core");
 48	if (IS_ERR(core->core_iomem)) {
 49		dev_err(dev, "couldn't find CORE registers %ld\n", PTR_ERR(core->core_iomem));
 50		return PTR_ERR(core->core_iomem);
 51	}
 52
 53	dma_set_max_seg_size(dev, UINT_MAX);
 54
 55	err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40));
 56	if (err)
 57		return err;
 58
 59	core->iommu_group = iommu_group_get(dev);
 60
 61	err = rocket_job_init(core);
 62	if (err) {
 63		iommu_group_put(core->iommu_group);
 64		core->iommu_group = NULL;
 65		return err;
 66	}
 67
 68	pm_runtime_use_autosuspend(dev);
 69
 70	/*
 71	 * As this NPU will be most often used as part of a media pipeline that
 72	 * ends presenting in a display, choose 50 ms (~3 frames at 60Hz) as an
 73	 * autosuspend delay as that will keep the device powered up while the
 74	 * pipeline is running.
 75	 */
 76	pm_runtime_set_autosuspend_delay(dev, 50);
 77
 78	pm_runtime_enable(dev);
 79
 80	err = pm_runtime_resume_and_get(dev);
 81	if (err) {
 82		rocket_core_fini(core);
 83		return err;
 84	}
 85
 86	version = rocket_pc_readl(core, VERSION);
 87	version += rocket_pc_readl(core, VERSION_NUM) & 0xffff;
 88
 89	pm_runtime_mark_last_busy(dev);
 90	pm_runtime_put_autosuspend(dev);
 91
 92	dev_info(dev, "Rockchip NPU core %d version: %d\n", core->index, version);
 93
 94	return 0;
 95}
 96
 97void rocket_core_fini(struct rocket_core *core)
 98{
 99	pm_runtime_dont_use_autosuspend(core->dev);
100	pm_runtime_disable(core->dev);
101	iommu_group_put(core->iommu_group);
102	core->iommu_group = NULL;
103	rocket_job_fini(core);
104}
105
106void rocket_core_reset(struct rocket_core *core)
107{
108	reset_control_bulk_assert(ARRAY_SIZE(core->resets), core->resets);
109
110	udelay(10);
111
112	reset_control_bulk_deassert(ARRAY_SIZE(core->resets), core->resets);
113}
~/ Read-only file preview.