*/
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);
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;
}
/*
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;
error_pll_ref:
clk_disable_unprepare(xvcu->pll_ref);
-error_aclk:
- clk_disable_unprepare(xvcu->aclk);
+
return ret;
}
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,
MODULE_AUTHOR("Dhaval Shah <dshah@xilinx.com>");
MODULE_DESCRIPTION("Xilinx VCU init Driver");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:xilinx-vcu");
--- /dev/null
+// 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");