diff options
Diffstat (limited to 'drivers/gpu/sprd_iommu/sprd_iommu_sysfs.c')
| -rw-r--r-- | drivers/gpu/sprd_iommu/sprd_iommu_sysfs.c | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/drivers/gpu/sprd_iommu/sprd_iommu_sysfs.c b/drivers/gpu/sprd_iommu/sprd_iommu_sysfs.c new file mode 100644 index 00000000..4bbc3061 --- /dev/null +++ b/drivers/gpu/sprd_iommu/sprd_iommu_sysfs.c @@ -0,0 +1,157 @@ +#include <linux/kernel.h> +#include <linux/fs.h> +#include <linux/device.h> +#include <linux/module.h> +#include <linux/clk.h> +#include <linux/seq_file.h> +#include <linux/debugfs.h> +#include <asm/uaccess.h> +#include <linux/module.h> +#include <linux/genalloc.h> +#include <linux/sprd_iommu.h> +#include "sprd_iommu_sysfs.h" + +static struct dentry *iommu_debugfs_dir = NULL; +extern int sprd_iommu_gsp_backup(struct sprd_iommu_dev *dev); +extern int sprd_iommu_gsp_restore(struct sprd_iommu_dev *dev); +extern int sprd_iommu_mm_backup(struct sprd_iommu_dev *dev); +extern int sprd_iommu_mm_restore(struct sprd_iommu_dev *dev); + +static void iova_dump_chunk_bitmap(struct gen_pool *pool, + struct gen_pool_chunk *chunk, void *data) +{ + struct seq_file *s = (struct seq_file *)data; + unsigned long nbits = ((chunk->end_addr - chunk->start_addr) + (1UL << 12) - 1) >> 12; + + seq_printf(s,"chunk phys_addr:0x%lx start_addr:0x%lx end_addr:0x%lx\n", + chunk->phys_addr, chunk->start_addr, chunk->end_addr); + seq_bitmap(s, chunk->bits, nbits); + seq_printf(s,"\n"); +} + +static int iova_show(struct seq_file *s, void *unused) +{ + struct sprd_iommu_dev *iommu_dev = (struct sprd_iommu_dev *)s->private; + + seq_printf(s,"iommu_name:%s iova_base:0x%lx iova_size:0x%zx\n", + iommu_dev->init_data->name, iommu_dev->init_data->iova_base, + iommu_dev->init_data->iova_size); + gen_pool_for_each_chunk(iommu_dev->pool, iova_dump_chunk_bitmap, s); + + return 0; +} + +static int iova_open(struct inode *inode, struct file *file) +{ + return single_open(file, iova_show, inode->i_private); +} + +static const struct file_operations iova_fops = { + .owner = THIS_MODULE, + .open = iova_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int pgt_show(struct seq_file *s, void *unused) +{ + struct sprd_iommu_dev *iommu_dev = (struct sprd_iommu_dev *)s->private; + unsigned long i = 0; + + seq_printf(s,"%s pgt_base:0x%lx pgt_size:0x%zx iova_base:0x%lx iova_size:0x%zx\n", + iommu_dev->init_data->name, + iommu_dev->init_data->pgt_base, iommu_dev->init_data->pgt_size, + iommu_dev->init_data->iova_base, iommu_dev->init_data->iova_size); + + mutex_lock(&iommu_dev->mutex_map); + if (iommu_dev->light_sleep_en) { + if (0 == iommu_dev->map_count) { + iommu_dev->ops->enable(iommu_dev); + iommu_dev->ops->open(iommu_dev); + } else { + iommu_dev->ops->enable(iommu_dev); + } + } else { + if (0 == iommu_dev->map_count) { + iommu_dev->ops->enable(iommu_dev); + } + } + + mutex_lock(&iommu_dev->mutex_pgt); + for (i = 0; i < (iommu_dev->init_data->pgt_size >> 2); i++) + { + if(i % 20 == 0) + { + seq_printf(s, "\n0x%lx[0x%lx]: ", + iommu_dev->init_data->pgt_base + i*4, + iommu_dev->init_data->iova_base + i*4096); + } + seq_printf(s, "%x,", + *(((uint32_t *)iommu_dev->init_data->pgt_base) + i)); + } + mutex_unlock(&iommu_dev->mutex_pgt); + + if (iommu_dev->light_sleep_en) { + if (0 == iommu_dev->map_count) { + iommu_dev->ops->release(iommu_dev); + iommu_dev->ops->disable(iommu_dev); + } else { + iommu_dev->ops->disable(iommu_dev); + } + } else { + if (0 == iommu_dev->map_count) { + iommu_dev->ops->disable(iommu_dev); + } + } + mutex_unlock(&iommu_dev->mutex_map); + + return 0; +} + +static int pgt_open(struct inode *inode, struct file *file) +{ + return single_open(file, pgt_show, inode->i_private); +} + +static const struct file_operations pgt_fops = { + .owner = THIS_MODULE, + .open = pgt_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +int sprd_iommu_sysfs_register(struct sprd_iommu_dev *device, + const char *dev_name) +{ + iommu_debugfs_dir = debugfs_create_dir(dev_name, NULL); + + if(ERR_PTR(-ENODEV) == iommu_debugfs_dir) + { + /* Debugfs not supported. */ + iommu_debugfs_dir = NULL; + } + else + { + if(NULL != iommu_debugfs_dir) + { + debugfs_create_file( + "iova", 0444, iommu_debugfs_dir, device, &iova_fops); + debugfs_create_file( + "pgtable", 0444, iommu_debugfs_dir, device, &pgt_fops); + } + } + return 0; +} + +int sprd_iommu_sysfs_unregister(struct sprd_iommu_dev *device, + const char *dev_name) +{ + if(NULL != iommu_debugfs_dir) + { + debugfs_remove_recursive(iommu_debugfs_dir); + } + + return 0; +} |
