cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mtk_vcodec_dec_hw.c (5004B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (c) 2021 MediaTek Inc.
      4 * Author: Yunfei Dong <yunfei.dong@mediatek.com>
      5 */
      6
      7#include <linux/interrupt.h>
      8#include <linux/irq.h>
      9#include <linux/module.h>
     10#include <linux/of.h>
     11#include <linux/of_device.h>
     12#include <linux/pm_runtime.h>
     13#include <linux/slab.h>
     14
     15#include "mtk_vcodec_drv.h"
     16#include "mtk_vcodec_dec.h"
     17#include "mtk_vcodec_dec_hw.h"
     18#include "mtk_vcodec_dec_pm.h"
     19#include "mtk_vcodec_intr.h"
     20#include "mtk_vcodec_util.h"
     21
     22static const struct of_device_id mtk_vdec_hw_match[] = {
     23	{
     24		.compatible = "mediatek,mtk-vcodec-lat",
     25		.data = (void *)MTK_VDEC_LAT0,
     26	},
     27	{
     28		.compatible = "mediatek,mtk-vcodec-core",
     29		.data = (void *)MTK_VDEC_CORE,
     30	},
     31	{},
     32};
     33MODULE_DEVICE_TABLE(of, mtk_vdec_hw_match);
     34
     35static int mtk_vdec_hw_prob_done(struct mtk_vcodec_dev *vdec_dev)
     36{
     37	struct platform_device *pdev = vdec_dev->plat_dev;
     38	struct device_node *subdev_node;
     39	enum mtk_vdec_hw_id hw_idx;
     40	const struct of_device_id *of_id;
     41	int i;
     42
     43	for (i = 0; i < ARRAY_SIZE(mtk_vdec_hw_match); i++) {
     44		of_id = &mtk_vdec_hw_match[i];
     45		subdev_node = of_find_compatible_node(NULL, NULL,
     46						      of_id->compatible);
     47		if (!subdev_node)
     48			continue;
     49
     50		of_node_put(subdev_node);
     51
     52		hw_idx = (enum mtk_vdec_hw_id)(uintptr_t)of_id->data;
     53		if (!test_bit(hw_idx, vdec_dev->subdev_bitmap)) {
     54			dev_err(&pdev->dev, "vdec %d is not ready", hw_idx);
     55			return -EAGAIN;
     56		}
     57	}
     58
     59	return 0;
     60}
     61
     62static irqreturn_t mtk_vdec_hw_irq_handler(int irq, void *priv)
     63{
     64	struct mtk_vdec_hw_dev *dev = priv;
     65	struct mtk_vcodec_ctx *ctx;
     66	u32 cg_status;
     67	unsigned int dec_done_status;
     68	void __iomem *vdec_misc_addr = dev->reg_base[VDEC_HW_MISC] +
     69					VDEC_IRQ_CFG_REG;
     70
     71	ctx = mtk_vcodec_get_curr_ctx(dev->main_dev, dev->hw_idx);
     72
     73	/* check if HW active or not */
     74	cg_status = readl(dev->reg_base[VDEC_HW_SYS]);
     75	if (cg_status & VDEC_HW_ACTIVE) {
     76		mtk_v4l2_err("vdec active is not 0x0 (0x%08x)",
     77			     cg_status);
     78		return IRQ_HANDLED;
     79	}
     80
     81	dec_done_status = readl(vdec_misc_addr);
     82	if ((dec_done_status & MTK_VDEC_IRQ_STATUS_DEC_SUCCESS) !=
     83	    MTK_VDEC_IRQ_STATUS_DEC_SUCCESS)
     84		return IRQ_HANDLED;
     85
     86	/* clear interrupt */
     87	writel(dec_done_status | VDEC_IRQ_CFG, vdec_misc_addr);
     88	writel(dec_done_status & ~VDEC_IRQ_CLR, vdec_misc_addr);
     89
     90	wake_up_ctx(ctx, MTK_INST_IRQ_RECEIVED, dev->hw_idx);
     91
     92	mtk_v4l2_debug(3, "wake up ctx %d, dec_done_status=%x",
     93		       ctx->id, dec_done_status);
     94
     95	return IRQ_HANDLED;
     96}
     97
     98static int mtk_vdec_hw_init_irq(struct mtk_vdec_hw_dev *dev)
     99{
    100	struct platform_device *pdev = dev->plat_dev;
    101	int ret;
    102
    103	dev->dec_irq = platform_get_irq(pdev, 0);
    104	if (dev->dec_irq < 0)
    105		return dev->dec_irq;
    106
    107	irq_set_status_flags(dev->dec_irq, IRQ_NOAUTOEN);
    108	ret = devm_request_irq(&pdev->dev, dev->dec_irq,
    109			       mtk_vdec_hw_irq_handler, 0, pdev->name, dev);
    110	if (ret) {
    111		dev_err(&pdev->dev, "Failed to install dev->dec_irq %d (%d)",
    112			dev->dec_irq, ret);
    113		return ret;
    114	}
    115
    116	return 0;
    117}
    118
    119static int mtk_vdec_hw_probe(struct platform_device *pdev)
    120{
    121	struct device *dev = &pdev->dev;
    122	struct mtk_vdec_hw_dev *subdev_dev;
    123	struct mtk_vcodec_dev *main_dev;
    124	const struct of_device_id *of_id;
    125	int hw_idx;
    126	int ret;
    127
    128	if (!dev->parent) {
    129		dev_err(dev, "no parent for hardware devices.\n");
    130		return -ENODEV;
    131	}
    132
    133	main_dev = dev_get_drvdata(dev->parent);
    134	if (!main_dev) {
    135		dev_err(dev, "failed to get parent driver data");
    136		return -EINVAL;
    137	}
    138
    139	subdev_dev = devm_kzalloc(dev, sizeof(*subdev_dev), GFP_KERNEL);
    140	if (!subdev_dev)
    141		return -ENOMEM;
    142
    143	subdev_dev->plat_dev = pdev;
    144	ret = mtk_vcodec_init_dec_clk(pdev, &subdev_dev->pm);
    145	if (ret)
    146		return ret;
    147	pm_runtime_enable(&pdev->dev);
    148
    149	of_id = of_match_device(mtk_vdec_hw_match, dev);
    150	if (!of_id) {
    151		dev_err(dev, "Can't get vdec subdev id.\n");
    152		ret = -EINVAL;
    153		goto err;
    154	}
    155
    156	hw_idx = (enum mtk_vdec_hw_id)(uintptr_t)of_id->data;
    157	if (hw_idx >= MTK_VDEC_HW_MAX) {
    158		dev_err(dev, "Hardware index %d not correct.\n", hw_idx);
    159		ret = -EINVAL;
    160		goto err;
    161	}
    162
    163	main_dev->subdev_dev[hw_idx] = subdev_dev;
    164	subdev_dev->hw_idx = hw_idx;
    165	subdev_dev->main_dev = main_dev;
    166	subdev_dev->reg_base[VDEC_HW_SYS] = main_dev->reg_base[VDEC_HW_SYS];
    167	set_bit(subdev_dev->hw_idx, main_dev->subdev_bitmap);
    168
    169	ret = mtk_vdec_hw_init_irq(subdev_dev);
    170	if (ret)
    171		goto err;
    172
    173	subdev_dev->reg_base[VDEC_HW_MISC] =
    174		devm_platform_ioremap_resource(pdev, 0);
    175	if (IS_ERR((__force void *)subdev_dev->reg_base[VDEC_HW_MISC])) {
    176		ret = PTR_ERR((__force void *)subdev_dev->reg_base[VDEC_HW_MISC]);
    177		goto err;
    178	}
    179
    180	if (!main_dev->subdev_prob_done)
    181		main_dev->subdev_prob_done = mtk_vdec_hw_prob_done;
    182
    183	platform_set_drvdata(pdev, subdev_dev);
    184	return 0;
    185err:
    186	pm_runtime_disable(subdev_dev->pm.dev);
    187	return ret;
    188}
    189
    190static struct platform_driver mtk_vdec_driver = {
    191	.probe	= mtk_vdec_hw_probe,
    192	.driver	= {
    193		.name	= "mtk-vdec-comp",
    194		.of_match_table = mtk_vdec_hw_match,
    195	},
    196};
    197module_platform_driver(mtk_vdec_driver);
    198
    199MODULE_LICENSE("GPL v2");
    200MODULE_DESCRIPTION("Mediatek video decoder hardware driver");