aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/xroeframer/xroe_framer.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/xroeframer/xroe_framer.c')
-rw-r--r--drivers/staging/xroeframer/xroe_framer.c155
1 files changed, 155 insertions, 0 deletions
diff --git a/drivers/staging/xroeframer/xroe_framer.c b/drivers/staging/xroeframer/xroe_framer.c
new file mode 100644
index 000000000000..dba7c69b010f
--- /dev/null
+++ b/drivers/staging/xroeframer/xroe_framer.c
@@ -0,0 +1,155 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 Xilinx, Inc.
+ *
+ * Vasileios Bimpikas <vasileios.bimpikas@xilinx.com>
+ */
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include "xroe_framer.h"
+
+#define DRIVER_NAME "framer"
+
+/*
+ * TODO: to be made static as well, so that multiple instances can be used. As
+ * of now, the "lp" structure is shared among the multiple source files
+ */
+struct framer_local *lp;
+static struct platform_driver framer_driver;
+/*
+ * TODO: placeholder for the IRQ once it's been implemented
+ * in the framer block
+ */
+static irqreturn_t framer_irq(int irq, void *lp)
+{
+ return IRQ_HANDLED;
+}
+
+/**
+ * framer_probe - Probes the device tree to locate the framer block
+ * @pdev: The structure containing the device's details
+ *
+ * Probes the device tree to locate the framer block and maps it to
+ * the kernel virtual memory space
+ *
+ * Return: 0 on success or a negative errno on error.
+ */
+static int framer_probe(struct platform_device *pdev)
+{
+ struct resource *r_mem; /* IO mem resources */
+ struct resource *r_irq;
+ struct device *dev = &pdev->dev;
+ int rc = 0;
+
+ dev_dbg(dev, "Device Tree Probing\n");
+ lp = devm_kzalloc(&pdev->dev, sizeof(*lp), GFP_KERNEL);
+ if (!lp)
+ return -ENOMEM;
+
+ /* Get iospace for the device */
+ r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ lp->base_addr = devm_ioremap_resource(&pdev->dev, r_mem);
+ if (IS_ERR(lp->base_addr))
+ return PTR_ERR(lp->base_addr);
+
+ dev_set_drvdata(dev, lp);
+ xroe_sysfs_init();
+ /* Get IRQ for the device */
+ /*
+ * TODO: No IRQ *yet* in the DT from the framer block, as it's still
+ * under development. To be added once it's in the block, and also
+ * replace with platform_get_irq_byname()
+ */
+ r_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (IS_ERR(r_irq)) {
+ dev_info(dev, "no IRQ found\n");
+ /*
+ * TODO: Return non-zero (error) code on no IRQ found.
+ * To be implemented once the IRQ is in the block
+ */
+ return 0;
+ }
+ rc = devm_request_irq(dev, lp->irq, &framer_irq, 0, DRIVER_NAME, lp);
+ if (rc) {
+ dev_err(dev, "testmodule: Could not allocate interrupt %d.\n",
+ lp->irq);
+ /*
+ * TODO: Return non-zero (error) code on no IRQ found.
+ * To be implemented once the IRQ is in the block
+ */
+ return 0;
+ }
+
+ return rc;
+}
+
+/**
+ * framer_init - Registers the driver
+ *
+ * Return: 0 on success, -1 on allocation error
+ *
+ * Registers the framer driver and creates character device drivers
+ * for the whole block, as well as separate ones for stats and
+ * radio control.
+ */
+static int __init framer_init(void)
+{
+ int ret;
+
+ pr_debug("XROE framer driver init\n");
+
+ ret = platform_driver_register(&framer_driver);
+
+ return ret;
+}
+
+/**
+ * framer_exit - Destroys the driver
+ *
+ * Unregisters the framer driver and destroys the character
+ * device driver for the whole block, as well as the separate ones
+ * for stats and radio control. Returns 0 upon successful execution
+ */
+static void __exit framer_exit(void)
+{
+ xroe_sysfs_exit();
+ platform_driver_unregister(&framer_driver);
+ pr_info("XROE Framer exit\n");
+}
+
+module_init(framer_init);
+module_exit(framer_exit);
+
+static const struct of_device_id framer_of_match[] = {
+ { .compatible = "xlnx,roe-framer-1.0", },
+ { /* end of list */ },
+};
+MODULE_DEVICE_TABLE(of, framer_of_match);
+
+static struct platform_driver framer_driver = {
+ .driver = {
+ /*
+ * TODO: .name shouldn't be necessary, though removing
+ * it results in kernel panic. To investigate further
+ */
+ .name = DRIVER_NAME,
+ .of_match_table = framer_of_match,
+ },
+ .probe = framer_probe,
+};
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Xilinx Inc.");
+MODULE_DESCRIPTION("framer - Xilinx Radio over Ethernet Framer driver");