diff options
-rw-r--r-- | Documentation/devicetree/bindings/soc/aspeed/aspeed-vga-sharedmem.txt | 20 | ||||
-rw-r--r-- | drivers/soc/aspeed/Kconfig | 8 | ||||
-rw-r--r-- | drivers/soc/aspeed/Makefile | 1 | ||||
-rw-r--r-- | drivers/soc/aspeed/aspeed-vga-sharedmem.c | 163 |
4 files changed, 192 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/soc/aspeed/aspeed-vga-sharedmem.txt b/Documentation/devicetree/bindings/soc/aspeed/aspeed-vga-sharedmem.txt new file mode 100644 index 000000000000..03f57c53e844 --- /dev/null +++ b/Documentation/devicetree/bindings/soc/aspeed/aspeed-vga-sharedmem.txt @@ -0,0 +1,20 @@ +* Aspeed VGA shared memory driver + +Aspeed VGA shared memory driver allow user to read data from AST2500 +VGA memory. This driver is required by ManagedDataRegionlV2 +specification. In the spec, BIOS will transfer whole SMBIOS table to +VGA memroy and BMC get the table from VGA memory. 0penBMC project do +not allow to use /dev/mem for security concerns. To get the data in +VGA shared memory in user space, implement this driver only allowed +user to mmap limited memory area. + +Required properties: +- compatible: "aspeed,ast2500-vga-sharedmem" + - aspeed,ast2500-vga-sharedmem: Aspeed AST2500 family +- reg: Should contain VGA shared memory start address and length + +Example: +vga-shared-memory { + compatible = "aspeed,ast2500-vga-sharedmem"; + reg = <0x9ff00000 0x100000>; +}; diff --git a/drivers/soc/aspeed/Kconfig b/drivers/soc/aspeed/Kconfig index 2b71518fadcb..aac7be9a63cc 100644 --- a/drivers/soc/aspeed/Kconfig +++ b/drivers/soc/aspeed/Kconfig @@ -76,6 +76,14 @@ config ASPEED_XDMA SoCs. The XDMA engine can perform PCIe DMA operations between the BMC and a host processor. +config ASPEED_VGA_SHAREDMEM + tristate "Aspeed VGA Shared memory" + help + To access VGA shared memory on Aspeed BMC, enable this option. + This driver used by ManagedDataRegionlV2 specification. In the + specification, BIOS will transfer whole SMBIOS table to VGA memory, + and BMC can get the table from VGA memory through this driver. + endmenu endif diff --git a/drivers/soc/aspeed/Makefile b/drivers/soc/aspeed/Makefile index ca301708ea19..68c04d02c2b2 100644 --- a/drivers/soc/aspeed/Makefile +++ b/drivers/soc/aspeed/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_ASPEED_UART_ROUTING) += aspeed-uart-routing.o obj-$(CONFIG_ASPEED_P2A_CTRL) += aspeed-p2a-ctrl.o obj-$(CONFIG_ASPEED_SOCINFO) += aspeed-socinfo.o obj-$(CONFIG_ASPEED_XDMA) += aspeed-xdma.o +obj-$(CONFIG_ASPEED_VGA_SHAREDMEM) += aspeed-vga-sharedmem.o diff --git a/drivers/soc/aspeed/aspeed-vga-sharedmem.c b/drivers/soc/aspeed/aspeed-vga-sharedmem.c new file mode 100644 index 000000000000..cd1f5431378c --- /dev/null +++ b/drivers/soc/aspeed/aspeed-vga-sharedmem.c @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 Intel Corporation + * VGA Shared Memory driver for Aspeed AST2500 + */ + +#include <linux/kernel.h> +#include <linux/miscdevice.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/of_platform.h> + +#define SHAREDMEM_NAME "vgasharedmem" + +struct aspeed_vga_sharedmem { + struct miscdevice miscdev; + unsigned int addr; + unsigned int size; + bool mmap_enable; +}; + +static struct aspeed_vga_sharedmem *file_sharemem(struct file *file) +{ + return container_of(file->private_data, + struct aspeed_vga_sharedmem, miscdev); +} + +static int vga_open(struct inode *inode, struct file *file) +{ + struct aspeed_vga_sharedmem *vga_sharedmem = file_sharemem(file); + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (!vga_sharedmem->mmap_enable) + return -EPERM; + + return 0; +} + +static int vga_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct aspeed_vga_sharedmem *vga_sharedmem = file_sharemem(file); + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + vma->vm_flags = (vma->vm_flags & (~VM_WRITE)); + remap_pfn_range(vma, vma->vm_start, vga_sharedmem->addr >> PAGE_SHIFT, + vga_sharedmem->size, vma->vm_page_prot); + return 0; +} + +static ssize_t enable_mmap_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct aspeed_vga_sharedmem *vga_sharedmem = dev_get_drvdata(dev); + + return sprintf(buf, "%u\n", vga_sharedmem->mmap_enable); +} + +static ssize_t enable_mmap_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct aspeed_vga_sharedmem *vga_sharedmem = + dev_get_drvdata(dev); + bool val; + + if (kstrtobool(buf, &val)) + return -EINVAL; + + vga_sharedmem->mmap_enable = val; + + return count; +} +static DEVICE_ATTR_RW(enable_mmap); + +static struct attribute *sharedmem_attrs[] = { + &dev_attr_enable_mmap.attr, + NULL +}; + +static const struct attribute_group sharedmem_attr_group = { + .attrs = sharedmem_attrs, +}; + +static const struct attribute_group *sharedmem_attr_groups[] = { + &sharedmem_attr_group, + NULL +}; + +static const struct file_operations vga_sharedmem_fops = { + .owner = THIS_MODULE, + .open = vga_open, + .mmap = vga_mmap, +}; + +static struct miscdevice vga_sharedmem_miscdev = { + .minor = MISC_DYNAMIC_MINOR, + .name = SHAREDMEM_NAME, + .fops = &vga_sharedmem_fops, + .groups = sharedmem_attr_groups, +}; + +static int vga_sharedmem_probe(struct platform_device *pdev) +{ + struct aspeed_vga_sharedmem *vga_sharedmem; + struct device *dev = &pdev->dev; + struct resource *rc; + + vga_sharedmem = devm_kzalloc(dev, sizeof(*vga_sharedmem), GFP_KERNEL); + if (!vga_sharedmem) + return -ENOMEM; + + dev_set_drvdata(&pdev->dev, vga_sharedmem); + + rc = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!rc) { + dev_err(dev, "Couldn't read size device-tree property\n"); + return -ENXIO; + } + + vga_sharedmem->addr = rc->start; + vga_sharedmem->size = resource_size(rc); + vga_sharedmem->mmap_enable = true; + + vga_sharedmem->miscdev = vga_sharedmem_miscdev; + + return misc_register(&vga_sharedmem->miscdev); +} + +static int vga_sharedmem_remove(struct platform_device *pdev) +{ + struct aspeed_vga_sharedmem *vga_sharedmem = + dev_get_drvdata(&pdev->dev); + + misc_deregister(&vga_sharedmem->miscdev); + + return 0; +} + +static const struct of_device_id vga_sharedmem_match[] = { + { .compatible = "aspeed,ast2500-vga-sharedmem", }, + { } +}; +MODULE_DEVICE_TABLE(of, vga_sharedmem_match); + +static struct platform_driver vga_sharedmem_driver = { + .driver = { + .name = "VGA-SHAREDMEM", + .of_match_table = vga_sharedmem_match, + }, + .probe = vga_sharedmem_probe, + .remove = vga_sharedmem_remove, +}; + +module_platform_driver(vga_sharedmem_driver); + +MODULE_AUTHOR("Yang Cheng <cheng.c.yang@intel.com>"); +MODULE_DESCRIPTION("Shared VGA memory"); +MODULE_LICENSE("GPL v2"); |