This patch adds zynq afi config driver. This is useful for the configuration of the PS-PL interface on zynq platform. Signed-off-by: Nava kishore Manne <nava.manne@xxxxxxxxxx> --- drivers/misc/Kconfig | 11 ++++++ drivers/misc/Makefile | 1 + drivers/misc/zynq-afi.c | 81 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 drivers/misc/zynq-afi.c diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index f532c59bb59b..877b43b3377d 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -445,6 +445,17 @@ config HISI_HIKEY_USB switching between the dual-role USB-C port and the USB-A host ports using only one USB controller. +config ZYNQ_AFI + tristate "Xilinx ZYNQ AFI support" + help + Zynq AFI driver support for writing to the AFI registers + for configuring PS_PL Bus-width. Xilinx Zynq SoC connect + the PS to the programmable logic (PL) through the AXI port. + This AXI port helps to establish the data path between the + PS and PL.In-order to establish the proper communication path + between PS and PL, the AXI port data path should be configured + with the proper Bus-width values + source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" source "drivers/misc/cb710/Kconfig" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 99b6f15a3c70..e9b03843100f 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -56,3 +56,4 @@ obj-$(CONFIG_HABANA_AI) += habanalabs/ obj-$(CONFIG_UACCE) += uacce/ obj-$(CONFIG_XILINX_SDFEC) += xilinx_sdfec.o obj-$(CONFIG_HISI_HIKEY_USB) += hisi_hikey_usb.o +obj-$(CONFIG_ZYNQ_AFI) += zynq-afi.o diff --git a/drivers/misc/zynq-afi.c b/drivers/misc/zynq-afi.c new file mode 100644 index 000000000000..04317d1bdb98 --- /dev/null +++ b/drivers/misc/zynq-afi.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Xilinx ZYNQ AFI driver. + * Copyright (c) 2018-2021 Xilinx Inc. + */ + +#include <linux/err.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> + +/* Registers and special values for doing register-based operations */ +#define AFI_RDCHAN_CTRL_OFFSET 0x00 +#define AFI_WRCHAN_CTRL_OFFSET 0x14 + +#define AFI_BUSWIDTH_MASK 0x01 + +/** + * struct afi_fpga - AFI register description + * @membase: pointer to register struct + * @afi_width: AFI bus width to be written + */ +struct zynq_afi_fpga { + void __iomem *membase; + u32 afi_width; +}; + +static int zynq_afi_fpga_probe(struct platform_device *pdev) +{ + struct zynq_afi_fpga *afi_fpga; + struct resource *res; + u32 reg_val; + u32 val; + + afi_fpga = devm_kzalloc(&pdev->dev, sizeof(*afi_fpga), GFP_KERNEL); + if (!afi_fpga) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + afi_fpga->membase = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(afi_fpga->membase)) + return PTR_ERR(afi_fpga->membase); + + val = device_property_read_u32(&pdev->dev, "xlnx,afi-width", + &afi_fpga->afi_width); + if (val) { + dev_err(&pdev->dev, "failed to get the afi bus width\n"); + return -EINVAL; + } + + reg_val = readl(afi_fpga->membase + AFI_RDCHAN_CTRL_OFFSET); + reg_val &= ~AFI_BUSWIDTH_MASK; + writel(reg_val | afi_fpga->afi_width, + afi_fpga->membase + AFI_RDCHAN_CTRL_OFFSET); + reg_val = readl(afi_fpga->membase + AFI_WRCHAN_CTRL_OFFSET); + reg_val &= ~AFI_BUSWIDTH_MASK; + writel(reg_val | afi_fpga->afi_width, + afi_fpga->membase + AFI_WRCHAN_CTRL_OFFSET); + + return 0; +} + +static const struct of_device_id zynq_afi_fpga_ids[] = { + { .compatible = "xlnx,zynq-afi-fpga" }, + { }, +}; +MODULE_DEVICE_TABLE(of, zynq_afi_fpga_ids); + +static struct platform_driver zynq_afi_fpga_driver = { + .driver = { + .name = "zynq-afi-fpga", + .of_match_table = zynq_afi_fpga_ids, + }, + .probe = zynq_afi_fpga_probe, +}; +module_platform_driver(zynq_afi_fpga_driver); + +MODULE_DESCRIPTION("ZYNQ FPGA AFI module"); +MODULE_AUTHOR("Nava kishore Manne <nava.manne@xxxxxxxxxx>"); +MODULE_LICENSE("GPL v2"); -- 2.18.0