soc: xilinx: vcu: use vcu-settings syscon registers
Switch the "logicoreip" registers to the new xlnx,vcu-settings binding to be able to read the settings if the settings are specified in a separate device tree node that is shared with other drivers. If the driver is not able to find a node with the new binding, fall back to check for the logicore register bank to be backwards compatible. Signed-off-by: Michael Tretter <m.tretter@pengutronix.de> Reviewed-by: Hyun Kwon <hyun.kwon@xilinx.com> Link: https://lore.kernel.org/r/20201109134818.4159342-4-m.tretter@pengutronix.de Signed-off-by: Michal Simek <michal.simek@xilinx.com>zero-sugar-mainline-defconfig
parent
a3857f89dd
commit
30b79eb1f9
|
@ -4,6 +4,7 @@ menu "Xilinx SoC drivers"
|
||||||
config XILINX_VCU
|
config XILINX_VCU
|
||||||
tristate "Xilinx VCU logicoreIP Init"
|
tristate "Xilinx VCU logicoreIP Init"
|
||||||
depends on HAS_IOMEM
|
depends on HAS_IOMEM
|
||||||
|
select REGMAP_MMIO
|
||||||
help
|
help
|
||||||
Provides the driver to enable and disable the isolation between the
|
Provides the driver to enable and disable the isolation between the
|
||||||
processing system and programmable logic part by using the logicoreIP
|
processing system and programmable logic part by using the logicoreIP
|
||||||
|
|
|
@ -10,39 +10,12 @@
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
|
#include <linux/mfd/syscon.h>
|
||||||
|
#include <linux/mfd/syscon/xlnx-vcu.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
/* Address map for different registers implemented in the VCU LogiCORE IP. */
|
|
||||||
#define VCU_ECODER_ENABLE 0x00
|
|
||||||
#define VCU_DECODER_ENABLE 0x04
|
|
||||||
#define VCU_MEMORY_DEPTH 0x08
|
|
||||||
#define VCU_ENC_COLOR_DEPTH 0x0c
|
|
||||||
#define VCU_ENC_VERTICAL_RANGE 0x10
|
|
||||||
#define VCU_ENC_FRAME_SIZE_X 0x14
|
|
||||||
#define VCU_ENC_FRAME_SIZE_Y 0x18
|
|
||||||
#define VCU_ENC_COLOR_FORMAT 0x1c
|
|
||||||
#define VCU_ENC_FPS 0x20
|
|
||||||
#define VCU_MCU_CLK 0x24
|
|
||||||
#define VCU_CORE_CLK 0x28
|
|
||||||
#define VCU_PLL_BYPASS 0x2c
|
|
||||||
#define VCU_ENC_CLK 0x30
|
|
||||||
#define VCU_PLL_CLK 0x34
|
|
||||||
#define VCU_ENC_VIDEO_STANDARD 0x38
|
|
||||||
#define VCU_STATUS 0x3c
|
|
||||||
#define VCU_AXI_ENC_CLK 0x40
|
|
||||||
#define VCU_AXI_DEC_CLK 0x44
|
|
||||||
#define VCU_AXI_MCU_CLK 0x48
|
|
||||||
#define VCU_DEC_VIDEO_STANDARD 0x4c
|
|
||||||
#define VCU_DEC_FRAME_SIZE_X 0x50
|
|
||||||
#define VCU_DEC_FRAME_SIZE_Y 0x54
|
|
||||||
#define VCU_DEC_FPS 0x58
|
|
||||||
#define VCU_BUFFER_B_FRAME 0x5c
|
|
||||||
#define VCU_WPP_EN 0x60
|
|
||||||
#define VCU_PLL_CLK_DEC 0x64
|
|
||||||
#define VCU_GASKET_INIT 0x74
|
|
||||||
#define VCU_GASKET_VALUE 0x03
|
|
||||||
|
|
||||||
/* vcu slcr registers, bitmask and shift */
|
/* vcu slcr registers, bitmask and shift */
|
||||||
#define VCU_PLL_CTRL 0x24
|
#define VCU_PLL_CTRL 0x24
|
||||||
|
@ -106,11 +79,20 @@ struct xvcu_device {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct clk *pll_ref;
|
struct clk *pll_ref;
|
||||||
struct clk *aclk;
|
struct clk *aclk;
|
||||||
void __iomem *logicore_reg_ba;
|
struct regmap *logicore_reg_ba;
|
||||||
void __iomem *vcu_slcr_ba;
|
void __iomem *vcu_slcr_ba;
|
||||||
u32 coreclk;
|
u32 coreclk;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct regmap_config vcu_settings_regmap_config = {
|
||||||
|
.name = "regmap",
|
||||||
|
.reg_bits = 32,
|
||||||
|
.val_bits = 32,
|
||||||
|
.reg_stride = 4,
|
||||||
|
.max_register = 0xfff,
|
||||||
|
.cache_type = REGCACHE_NONE,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct xvcu_pll_cfg - Helper data
|
* struct xvcu_pll_cfg - Helper data
|
||||||
* @fbdiv: The integer portion of the feedback divider to the PLL
|
* @fbdiv: The integer portion of the feedback divider to the PLL
|
||||||
|
@ -300,10 +282,12 @@ static int xvcu_set_vcu_pll_info(struct xvcu_device *xvcu)
|
||||||
int ret, i;
|
int ret, i;
|
||||||
const struct xvcu_pll_cfg *found = NULL;
|
const struct xvcu_pll_cfg *found = NULL;
|
||||||
|
|
||||||
inte = xvcu_read(xvcu->logicore_reg_ba, VCU_PLL_CLK);
|
regmap_read(xvcu->logicore_reg_ba, VCU_PLL_CLK, &inte);
|
||||||
deci = xvcu_read(xvcu->logicore_reg_ba, VCU_PLL_CLK_DEC);
|
regmap_read(xvcu->logicore_reg_ba, VCU_PLL_CLK_DEC, &deci);
|
||||||
coreclk = xvcu_read(xvcu->logicore_reg_ba, VCU_CORE_CLK) * MHZ;
|
regmap_read(xvcu->logicore_reg_ba, VCU_CORE_CLK, &coreclk);
|
||||||
mcuclk = xvcu_read(xvcu->logicore_reg_ba, VCU_MCU_CLK) * MHZ;
|
coreclk *= MHZ;
|
||||||
|
regmap_read(xvcu->logicore_reg_ba, VCU_MCU_CLK, &mcuclk);
|
||||||
|
mcuclk *= MHZ;
|
||||||
if (!mcuclk || !coreclk) {
|
if (!mcuclk || !coreclk) {
|
||||||
dev_err(xvcu->dev, "Invalid mcu and core clock data\n");
|
dev_err(xvcu->dev, "Invalid mcu and core clock data\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -498,6 +482,7 @@ static int xvcu_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
struct xvcu_device *xvcu;
|
struct xvcu_device *xvcu;
|
||||||
|
void __iomem *regs;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
xvcu = devm_kzalloc(&pdev->dev, sizeof(*xvcu), GFP_KERNEL);
|
xvcu = devm_kzalloc(&pdev->dev, sizeof(*xvcu), GFP_KERNEL);
|
||||||
|
@ -518,19 +503,34 @@ static int xvcu_probe(struct platform_device *pdev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "logicore");
|
xvcu->logicore_reg_ba =
|
||||||
|
syscon_regmap_lookup_by_compatible("xlnx,vcu-settings");
|
||||||
|
if (IS_ERR(xvcu->logicore_reg_ba)) {
|
||||||
|
dev_info(&pdev->dev,
|
||||||
|
"could not find xlnx,vcu-settings: trying direct register access\n");
|
||||||
|
|
||||||
|
res = platform_get_resource_byname(pdev,
|
||||||
|
IORESOURCE_MEM, "logicore");
|
||||||
if (!res) {
|
if (!res) {
|
||||||
dev_err(&pdev->dev, "get logicore memory resource failed.\n");
|
dev_err(&pdev->dev, "get logicore memory resource failed.\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
xvcu->logicore_reg_ba = devm_ioremap(&pdev->dev, res->start,
|
regs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
|
||||||
resource_size(res));
|
if (!regs) {
|
||||||
if (!xvcu->logicore_reg_ba) {
|
|
||||||
dev_err(&pdev->dev, "logicore register mapping failed.\n");
|
dev_err(&pdev->dev, "logicore register mapping failed.\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xvcu->logicore_reg_ba =
|
||||||
|
devm_regmap_init_mmio(&pdev->dev, regs,
|
||||||
|
&vcu_settings_regmap_config);
|
||||||
|
if (IS_ERR(xvcu->logicore_reg_ba)) {
|
||||||
|
dev_err(&pdev->dev, "failed to init regmap\n");
|
||||||
|
return PTR_ERR(xvcu->logicore_reg_ba);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
xvcu->aclk = devm_clk_get(&pdev->dev, "aclk");
|
xvcu->aclk = devm_clk_get(&pdev->dev, "aclk");
|
||||||
if (IS_ERR(xvcu->aclk)) {
|
if (IS_ERR(xvcu->aclk)) {
|
||||||
dev_err(&pdev->dev, "Could not get aclk clock\n");
|
dev_err(&pdev->dev, "Could not get aclk clock\n");
|
||||||
|
@ -560,7 +560,7 @@ static int xvcu_probe(struct platform_device *pdev)
|
||||||
* Bit 0 : Gasket isolation
|
* Bit 0 : Gasket isolation
|
||||||
* Bit 1 : put VCU out of reset
|
* Bit 1 : put VCU out of reset
|
||||||
*/
|
*/
|
||||||
xvcu_write(xvcu->logicore_reg_ba, VCU_GASKET_INIT, VCU_GASKET_VALUE);
|
regmap_write(xvcu->logicore_reg_ba, VCU_GASKET_INIT, VCU_GASKET_VALUE);
|
||||||
|
|
||||||
/* Do the PLL Settings based on the ref clk,core and mcu clk freq */
|
/* Do the PLL Settings based on the ref clk,core and mcu clk freq */
|
||||||
ret = xvcu_set_pll(xvcu);
|
ret = xvcu_set_pll(xvcu);
|
||||||
|
@ -597,7 +597,7 @@ static int xvcu_remove(struct platform_device *pdev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
/* Add the the Gasket isolation and put the VCU in reset. */
|
/* Add the the Gasket isolation and put the VCU in reset. */
|
||||||
xvcu_write(xvcu->logicore_reg_ba, VCU_GASKET_INIT, 0);
|
regmap_write(xvcu->logicore_reg_ba, VCU_GASKET_INIT, 0);
|
||||||
|
|
||||||
clk_disable_unprepare(xvcu->pll_ref);
|
clk_disable_unprepare(xvcu->pll_ref);
|
||||||
clk_disable_unprepare(xvcu->aclk);
|
clk_disable_unprepare(xvcu->aclk);
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Pengutronix, Michael Tretter <kernel@pengutronix.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XLNX_VCU_H
|
||||||
|
#define __XLNX_VCU_H
|
||||||
|
|
||||||
|
#define VCU_ECODER_ENABLE 0x00
|
||||||
|
#define VCU_DECODER_ENABLE 0x04
|
||||||
|
#define VCU_MEMORY_DEPTH 0x08
|
||||||
|
#define VCU_ENC_COLOR_DEPTH 0x0c
|
||||||
|
#define VCU_ENC_VERTICAL_RANGE 0x10
|
||||||
|
#define VCU_ENC_FRAME_SIZE_X 0x14
|
||||||
|
#define VCU_ENC_FRAME_SIZE_Y 0x18
|
||||||
|
#define VCU_ENC_COLOR_FORMAT 0x1c
|
||||||
|
#define VCU_ENC_FPS 0x20
|
||||||
|
#define VCU_MCU_CLK 0x24
|
||||||
|
#define VCU_CORE_CLK 0x28
|
||||||
|
#define VCU_PLL_BYPASS 0x2c
|
||||||
|
#define VCU_ENC_CLK 0x30
|
||||||
|
#define VCU_PLL_CLK 0x34
|
||||||
|
#define VCU_ENC_VIDEO_STANDARD 0x38
|
||||||
|
#define VCU_STATUS 0x3c
|
||||||
|
#define VCU_AXI_ENC_CLK 0x40
|
||||||
|
#define VCU_AXI_DEC_CLK 0x44
|
||||||
|
#define VCU_AXI_MCU_CLK 0x48
|
||||||
|
#define VCU_DEC_VIDEO_STANDARD 0x4c
|
||||||
|
#define VCU_DEC_FRAME_SIZE_X 0x50
|
||||||
|
#define VCU_DEC_FRAME_SIZE_Y 0x54
|
||||||
|
#define VCU_DEC_FPS 0x58
|
||||||
|
#define VCU_BUFFER_B_FRAME 0x5c
|
||||||
|
#define VCU_WPP_EN 0x60
|
||||||
|
#define VCU_PLL_CLK_DEC 0x64
|
||||||
|
#define VCU_GASKET_INIT 0x74
|
||||||
|
#define VCU_GASKET_VALUE 0x03
|
||||||
|
|
||||||
|
#endif /* __XLNX_VCU_H */
|
Loading…
Reference in New Issue