]> rtime.felk.cvut.cz Git - zynq/linux.git/commitdiff
soc: xilinx: Add VCU MFD core driver
authorRajan Vaja <rajan.vaja@xilinx.com>
Mon, 10 Sep 2018 05:37:33 +0000 (22:37 -0700)
committerMichal Simek <michal.simek@xilinx.com>
Wed, 7 Nov 2018 10:03:46 +0000 (11:03 +0100)
Add VCU MFD core driver. This drivers provides two
functionalities:
  1. Clock controller - Registers VCU clocks to CCF which
are used by VCU init driver.
  2. VCU init driver  - Performs initialization required by
VCU encoder and decoder driver.

Core driver registers above MFD devices and removes gasket
isolation as a pre-requisite to access logicore registers.

Signed-off-by: Rajan Vaja <rajan.vaja@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
drivers/soc/xilinx/Kconfig
drivers/soc/xilinx/Makefile
drivers/soc/xilinx/xlnx_vcu.c
drivers/soc/xilinx/xlnx_vcu_core.c [new file with mode: 0644]
include/soc/xilinx/xlnx_vcu.h

index 1c98d7f056197eaf914196bb8e0c4c32e9949b6b..f1873dfd34881cbc492d98ae2380e389c8b12db1 100644 (file)
@@ -3,6 +3,7 @@ menu "Xilinx SoC drivers"
 
 config XILINX_VCU
        tristate "Xilinx VCU logicoreIP Init"
+       select MFD_CORE
        depends on HAS_IOMEM
        help
          Provides the driver to enable and disable the isolation between the
index e132897738752146300bc3c55775a5df3e56f250..14ba31039aea351b559b91c78a3480237ab30d53 100644 (file)
@@ -1,4 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_XILINX_VCU)       += xlnx_vcu.o
+obj-$(CONFIG_XILINX_VCU)       += xlnx_vcu_core.o xlnx_vcu.o
 
 obj-$(CONFIG_ARCH_ZYNQMP)      += zynqmp/
index 0ed301d2dfd6d57ecf6d944930338e0642a55c55..8d0403e8965e3a7c4d0f22a0190fad96a62b03ec 100644 (file)
@@ -541,8 +541,8 @@ static int xvcu_set_pll(struct xvcu_device *xvcu)
  */
 static int xvcu_probe(struct platform_device *pdev)
 {
-       struct resource *res;
        struct xvcu_device *xvcu;
+       struct xvcu_device *xvcu_core = dev_get_drvdata(pdev->dev.parent);
        int ret;
 
        xvcu = devm_kzalloc(&pdev->dev, sizeof(*xvcu), GFP_KERNEL);
@@ -550,54 +550,19 @@ static int xvcu_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        xvcu->dev = &pdev->dev;
-       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vcu_slcr");
-       if (!res) {
-               dev_err(&pdev->dev, "get vcu_slcr memory resource failed.\n");
-               return -ENODEV;
-       }
-
-       xvcu->vcu_slcr_ba = devm_ioremap_nocache(&pdev->dev, res->start,
-                                                resource_size(res));
-       if (!xvcu->vcu_slcr_ba) {
-               dev_err(&pdev->dev, "vcu_slcr register mapping failed.\n");
-               return -ENOMEM;
-       }
-
-       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "logicore");
-       if (!res) {
-               dev_err(&pdev->dev, "get logicore memory resource failed.\n");
-               return -ENODEV;
-       }
-
-       xvcu->logicore_reg_ba = devm_ioremap_nocache(&pdev->dev, res->start,
-                                                    resource_size(res));
-       if (!xvcu->logicore_reg_ba) {
-               dev_err(&pdev->dev, "logicore register mapping failed.\n");
-               return -ENOMEM;
-       }
+       xvcu->vcu_slcr_ba = xvcu_core->vcu_slcr_ba;
+       xvcu->logicore_reg_ba = xvcu_core->logicore_reg_ba;
 
-       xvcu->aclk = devm_clk_get(&pdev->dev, "aclk");
-       if (IS_ERR(xvcu->aclk)) {
-               dev_err(&pdev->dev, "Could not get aclk clock\n");
-               return PTR_ERR(xvcu->aclk);
-       }
-
-       xvcu->pll_ref = devm_clk_get(&pdev->dev, "pll_ref");
+       xvcu->pll_ref = devm_clk_get(pdev->dev.parent, "pll_ref");
        if (IS_ERR(xvcu->pll_ref)) {
                dev_err(&pdev->dev, "Could not get pll_ref clock\n");
                return PTR_ERR(xvcu->pll_ref);
        }
 
-       ret = clk_prepare_enable(xvcu->aclk);
-       if (ret) {
-               dev_err(&pdev->dev, "aclk clock enable failed\n");
-               return ret;
-       }
-
        ret = clk_prepare_enable(xvcu->pll_ref);
        if (ret) {
                dev_err(&pdev->dev, "pll_ref clock enable failed\n");
-               goto error_aclk;
+               return ret;
        }
 
        /*
@@ -616,7 +581,7 @@ static int xvcu_probe(struct platform_device *pdev)
 
        dev_set_drvdata(&pdev->dev, xvcu);
 
-       ret = of_platform_populate(xvcu->dev->of_node, NULL, NULL, &pdev->dev);
+       ret = devm_of_platform_populate(pdev->dev.parent);
        if (ret) {
                dev_err(&pdev->dev, "Failed to register allegro codecs\n");
                goto error_pll_ref;
@@ -627,8 +592,7 @@ static int xvcu_probe(struct platform_device *pdev)
 
 error_pll_ref:
        clk_disable_unprepare(xvcu->pll_ref);
-error_aclk:
-       clk_disable_unprepare(xvcu->aclk);
+
        return ret;
 }
 
@@ -648,28 +612,14 @@ static int xvcu_remove(struct platform_device *pdev)
        if (!xvcu)
                return -ENODEV;
 
-       of_platform_depopulate(&pdev->dev);
-
-       /* Add the the Gasket isolation and put the VCU in reset. */
-       xvcu_write(xvcu->logicore_reg_ba, VCU_GASKET_INIT, 0);
-
        clk_disable_unprepare(xvcu->pll_ref);
-       clk_disable_unprepare(xvcu->aclk);
 
        return 0;
 }
 
-static const struct of_device_id xvcu_of_id_table[] = {
-       { .compatible = "xlnx,vcu" },
-       { .compatible = "xlnx,vcu-logicoreip-1.0" },
-       { }
-};
-MODULE_DEVICE_TABLE(of, xvcu_of_id_table);
-
 static struct platform_driver xvcu_driver = {
        .driver = {
                .name           = "xilinx-vcu",
-               .of_match_table = xvcu_of_id_table,
        },
        .probe                  = xvcu_probe,
        .remove                 = xvcu_remove,
@@ -680,3 +630,4 @@ module_platform_driver(xvcu_driver);
 MODULE_AUTHOR("Dhaval Shah <dshah@xilinx.com>");
 MODULE_DESCRIPTION("Xilinx VCU init Driver");
 MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:xilinx-vcu");
diff --git a/drivers/soc/xilinx/xlnx_vcu_core.c b/drivers/soc/xilinx/xlnx_vcu_core.c
new file mode 100644 (file)
index 0000000..156793b
--- /dev/null
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx VCU core driver
+ *
+ * Copyright (C) 2018 Xilinx, Inc.
+ *
+ * Rajan Vaja <rajan.vaja@xilinx.com>
+ */
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <soc/xilinx/xlnx_vcu.h>
+
+static const struct mfd_cell xvcu_devs[] = {
+       {
+               .name = "xilinx-vcu",
+       },
+};
+
+static int xvcu_core_probe(struct platform_device *pdev)
+{
+       struct xvcu_device *xvcu;
+       struct resource *res;
+       int ret;
+
+       xvcu = devm_kzalloc(&pdev->dev, sizeof(*xvcu), GFP_KERNEL);
+       if (!xvcu)
+               return -ENOMEM;
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vcu_slcr");
+       if (!res) {
+               dev_err(&pdev->dev, "get vcu_slcr memory resource failed.\n");
+               return -ENODEV;
+       }
+
+       xvcu->vcu_slcr_ba = devm_ioremap_nocache(&pdev->dev, res->start,
+                                                resource_size(res));
+       if (!xvcu->vcu_slcr_ba) {
+               dev_err(&pdev->dev, "vcu_slcr register mapping failed.\n");
+               return -ENOMEM;
+       }
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "logicore");
+       if (!res) {
+               dev_err(&pdev->dev, "get logicore memory resource failed.\n");
+               return -ENODEV;
+       }
+
+       xvcu->logicore_reg_ba = devm_ioremap_nocache(&pdev->dev, res->start,
+                                                    resource_size(res));
+       if (!xvcu->logicore_reg_ba) {
+               dev_err(&pdev->dev, "logicore register mapping failed.\n");
+               return -ENOMEM;
+       }
+
+       dev_set_drvdata(&pdev->dev, xvcu);
+
+       xvcu->aclk = devm_clk_get(&pdev->dev, "aclk");
+       if (IS_ERR(xvcu->aclk)) {
+               dev_err(&pdev->dev, "Could not get aclk clock\n");
+               return PTR_ERR(xvcu->aclk);
+       }
+
+       ret = clk_prepare_enable(xvcu->aclk);
+       if (ret) {
+               dev_err(&pdev->dev, "aclk clock enable failed\n");
+               return ret;
+       }
+
+       /*
+        * Do the Gasket isolation and put the VCU out of reset
+        * Bit 0 : Gasket isolation
+        * Bit 1 : put VCU out of reset
+        */
+       iowrite32(VCU_GASKET_VALUE, xvcu->logicore_reg_ba + VCU_GASKET_INIT);
+
+       ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, xvcu_devs,
+                             ARRAY_SIZE(xvcu_devs), NULL, 0, NULL);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to add MFD devices %d\n", ret);
+               goto err_mfd_add_devices;
+       }
+
+       dev_dbg(&pdev->dev, "Successfully added MFD devices\n");
+
+       return 0;
+
+err_mfd_add_devices:
+       /* Add the the Gasket isolation and put the VCU in reset. */
+       iowrite32(0, xvcu->logicore_reg_ba + VCU_GASKET_INIT);
+
+       clk_disable_unprepare(xvcu->aclk);
+
+       return ret;
+}
+
+static int xvcu_core_remove(struct platform_device *pdev)
+{
+       struct xvcu_device *xvcu;
+
+       xvcu = platform_get_drvdata(pdev);
+       if (!xvcu)
+               return -ENODEV;
+
+       mfd_remove_devices(&pdev->dev);
+
+       /* Add the the Gasket isolation and put the VCU in reset. */
+       iowrite32(0, xvcu->logicore_reg_ba + VCU_GASKET_INIT);
+
+       clk_disable_unprepare(xvcu->aclk);
+
+       return 0;
+}
+
+static const struct of_device_id xvcu_core_of_id_table[] = {
+       { .compatible = "xlnx,vcu" },
+       { .compatible = "xlnx,vcu-logicoreip-1.0" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, xvcu_core_of_id_table);
+
+static struct platform_driver xvcu_core_driver = {
+       .driver = {
+               .name = "xilinx-vcu-core",
+               .of_match_table = xvcu_core_of_id_table,
+       },
+       .probe = xvcu_core_probe,
+       .remove = xvcu_core_remove,
+};
+
+module_platform_driver(xvcu_core_driver);
+
+MODULE_AUTHOR("Rajan Vaja <rajan.vaja@xilinx.com>");
+MODULE_DESCRIPTION("Xilinx VCU core Driver");
+MODULE_LICENSE("GPL v2");
index 3e8b77a8817aabb1971b3688028f317dd0cf56b7..3bb14f356b96119d2b75a22464ddce209643de42 100644 (file)
@@ -10,6 +10,9 @@
 #ifndef _XILINX_VCU_H_
 #define _XILINX_VCU_H_
 
+#define VCU_GASKET_INIT                        0x74
+#define VCU_GASKET_VALUE               0x03
+
 /**
  * struct xvcu_device - Xilinx VCU init device structure
  * @dev: Platform device