1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
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;
}
|