| From 9eac502eacd36a4975ec34a3f076594fa4364032 Mon Sep 17 00:00:00 2001 |
| From: Emekcan <emekcan.aras@arm.com> |
| Date: Fri, 19 Aug 2022 14:51:08 +0100 |
| Subject: [PATCH] Add external system driver |
| |
| Adds external system driver to control it |
| from user-space. It provides run and reset |
| functionality at the moment. |
| |
| Upstream-Status: Pending [Not submitted to upstream yet] |
| Signed-off-by: Emekcan Aras <emekcan.aras@arm.com> |
| Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org> |
| --- |
| drivers/misc/Kconfig | 1 + |
| drivers/misc/Makefile | 1 + |
| drivers/misc/arm/Kconfig | 5 ++ |
| drivers/misc/arm/Makefile | 1 + |
| drivers/misc/arm/extsys_ctrl.c | 151 +++++++++++++++++++++++++++++++++ |
| 5 files changed, 159 insertions(+) |
| create mode 100644 drivers/misc/arm/Kconfig |
| create mode 100644 drivers/misc/arm/Makefile |
| create mode 100644 drivers/misc/arm/extsys_ctrl.c |
| |
| diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig |
| index 433aa4197785..912986abc46c 100644 |
| --- a/drivers/misc/Kconfig |
| +++ b/drivers/misc/Kconfig |
| @@ -555,4 +555,5 @@ source "drivers/misc/cardreader/Kconfig" |
| source "drivers/misc/uacce/Kconfig" |
| source "drivers/misc/pvpanic/Kconfig" |
| source "drivers/misc/mchp_pci1xxxx/Kconfig" |
| +source "drivers/misc/arm/Kconfig" |
| endmenu |
| diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile |
| index 56de43943cd5..22e6561b8192 100644 |
| --- a/drivers/misc/Makefile |
| +++ b/drivers/misc/Makefile |
| @@ -63,5 +63,6 @@ obj-$(CONFIG_HI6421V600_IRQ) += hi6421v600-irq.o |
| obj-$(CONFIG_OPEN_DICE) += open-dice.o |
| obj-$(CONFIG_GP_PCI1XXXX) += mchp_pci1xxxx/ |
| obj-$(CONFIG_VCPU_STALL_DETECTOR) += vcpu_stall_detector.o |
| +obj-y += arm/ |
| obj-$(CONFIG_TMR_MANAGER) += xilinx_tmr_manager.o |
| obj-$(CONFIG_TMR_INJECT) += xilinx_tmr_inject.o |
| diff --git a/drivers/misc/arm/Kconfig b/drivers/misc/arm/Kconfig |
| new file mode 100644 |
| index 000000000000..9f1eb284e530 |
| --- /dev/null |
| +++ b/drivers/misc/arm/Kconfig |
| @@ -0,0 +1,5 @@ |
| +config EXTSYS_CTRL |
| + tristate "Arm External System control driver" |
| + help |
| + Say y here to enable support for external system control |
| + driver for the Arm Corstone-700 and Corstone1000 platform |
| \ No newline at end of file |
| diff --git a/drivers/misc/arm/Makefile b/drivers/misc/arm/Makefile |
| new file mode 100644 |
| index 000000000000..1ca3084cf8a0 |
| --- /dev/null |
| +++ b/drivers/misc/arm/Makefile |
| @@ -0,0 +1 @@ |
| +obj-$(CONFIG_EXTSYS_CTRL) += extsys_ctrl.o |
| diff --git a/drivers/misc/arm/extsys_ctrl.c b/drivers/misc/arm/extsys_ctrl.c |
| new file mode 100644 |
| index 000000000000..7929070ff43d |
| --- /dev/null |
| +++ b/drivers/misc/arm/extsys_ctrl.c |
| @@ -0,0 +1,151 @@ |
| +// SPDX-License-Identifier: GPL-2.0 |
| +/* |
| + * Arm Corstone700 and Corstone1000 external system reset control driver |
| + * |
| + * Copyright (C) 2019 Arm Ltd. |
| + * |
| + */ |
| + |
| +#include <linux/fs.h> |
| +#include <linux/clk.h> |
| +#include <linux/err.h> |
| +#include <linux/interrupt.h> |
| +#include <linux/io.h> |
| +#include <linux/kernel.h> |
| +#include <linux/mod_devicetable.h> |
| +#include <linux/module.h> |
| +#include <linux/platform_device.h> |
| +#include <linux/miscdevice.h> |
| +#include <linux/init.h> |
| + |
| +#define EXTSYS_DRV_NAME "extsys_ctrl" |
| +#define EXTSYS_MAX_DEVS 4 |
| + |
| +#define EXTSYS_RST_SIZE U(0x8) |
| +#define EXTSYS_RST_CTRL_OFF U(0x0) |
| +#define EXTSYS_RST_ST_OFF U(0x4) |
| + |
| +/* External system reset control indexes */ |
| +#define EXTSYS_CPU_WAIT (0x0) |
| +#define EXTSYS_RST_REQ (0x1) |
| + |
| +/* External system reset status masks */ |
| +#define EXTSYS_RST_ST_ACK_OFF U(0x1) |
| + |
| +/* No Reset Requested */ |
| +#define EXTSYS_RST_ST_ACK_NRR (0x0 << EXTSYS_RST_ST_ACK_OFF) |
| + |
| +/* Reset Request Complete */ |
| +#define EXTSYS_RST_ST_ACK_RRC (0x2 << EXTSYS_RST_ST_ACK_OFF) |
| + |
| +/* Reset Request Unable to Complete */ |
| +#define EXTSYS_RST_ST_ACK_RRUC (0x3 << EXTSYS_RST_ST_ACK_OFF) |
| + |
| +/* IOCTL commands */ |
| +#define EXTSYS_CPU_WAIT_DISABLE 0x0 |
| +#define EXTSYS_RESET_REQ_ENABLE 0x1 |
| + |
| +struct extsys_ctrl { |
| + struct miscdevice miscdev; |
| + void __iomem *reset_reg; |
| + void __iomem *set_reg; |
| +}; |
| + |
| +#define CLEAR_BIT(addr, index) writel(readl(addr) & ~(1UL << index), addr) |
| +#define SET_BIT(addr, index) writel(readl(addr) | (1UL << index), addr) |
| + |
| +static long extsys_ctrl_ioctl(struct file *f, unsigned int cmd, |
| + unsigned long arg) |
| +{ |
| + struct extsys_ctrl *extsys; |
| + |
| + extsys = container_of(f->private_data, struct extsys_ctrl, miscdev); |
| + |
| + switch (cmd) { |
| + case EXTSYS_CPU_WAIT_DISABLE: |
| + CLEAR_BIT(extsys->reset_reg, EXTSYS_CPU_WAIT); |
| + break; |
| + case EXTSYS_RESET_REQ_ENABLE: |
| + SET_BIT(extsys->reset_reg, EXTSYS_RST_REQ); |
| + break; |
| + default: |
| + break; |
| + } |
| + |
| + return 0; |
| +} |
| + |
| +static const struct file_operations extsys_ctrl_fops = { |
| + .owner = THIS_MODULE, |
| + .unlocked_ioctl = extsys_ctrl_ioctl, |
| +}; |
| + |
| +static int extsys_ctrl_probe(struct platform_device *pdev) |
| +{ |
| + struct device *dev = &pdev->dev; |
| + struct extsys_ctrl *extsys; |
| + struct resource *res; |
| + void __iomem *reset_reg; |
| + void __iomem *set_reg; |
| + int ret; |
| + |
| + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rstreg"); |
| + reset_reg = devm_ioremap_resource(dev, res); |
| + if (IS_ERR(reset_reg)) |
| + return PTR_ERR(reset_reg); |
| + |
| + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "streg"); |
| + set_reg = devm_ioremap_resource(dev, res); |
| + if (IS_ERR(set_reg)) |
| + return PTR_ERR(set_reg); |
| + |
| + extsys = devm_kzalloc(dev, sizeof(*extsys), GFP_KERNEL); |
| + if (!extsys) |
| + return -ENOMEM; |
| + |
| + extsys->reset_reg = reset_reg; |
| + extsys->set_reg = set_reg; |
| + |
| + extsys->miscdev.minor = MISC_DYNAMIC_MINOR; |
| + extsys->miscdev.name = EXTSYS_DRV_NAME; |
| + extsys->miscdev.fops = &extsys_ctrl_fops; |
| + extsys->miscdev.parent = dev; |
| + |
| + ret = misc_register(&extsys->miscdev); |
| + if (ret) |
| + return ret; |
| + |
| + dev_info(dev, "external system controller ready\n"); |
| + |
| + return 0; |
| +} |
| + |
| +static int extsys_ctrl_remove(struct platform_device *pdev) |
| +{ |
| + struct extsys_ctrl *extsys = dev_get_drvdata(&pdev->dev); |
| + |
| + misc_deregister(&extsys->miscdev); |
| + |
| + return 0; |
| +} |
| + |
| +static const struct of_device_id extsys_ctrl_match[] = { |
| + { .compatible = "arm,extsys_ctrl" }, |
| + { }, |
| +}; |
| +MODULE_DEVICE_TABLE(of, extsys_ctrl_match); |
| + |
| +static struct platform_driver extsys_ctrl_driver = { |
| + .driver = { |
| + .name = EXTSYS_DRV_NAME, |
| + .of_match_table = extsys_ctrl_match, |
| + }, |
| + .probe = extsys_ctrl_probe, |
| + .remove = extsys_ctrl_remove, |
| +}; |
| +module_platform_driver(extsys_ctrl_driver); |
| + |
| +MODULE_LICENSE("GPL v2"); |
| +MODULE_DESCRIPTION("Arm External System Control Driver"); |
| +MODULE_AUTHOR("Morten Borup Petersen"); |
| +MODULE_AUTHOR("Rui Miguel Silva <rui.silva@arm.com>"); |