This source file includes following definitions.
- opal_scom_unmangle
- opal_scom_read
- opal_scom_write
- scom_debug_read
- scom_debug_write
- scom_debug_init_one
- scom_debug_init
1
2
3
4
5
6
7
8
9
10
11 #include <linux/kernel.h>
12 #include <linux/of.h>
13 #include <linux/bug.h>
14 #include <linux/gfp.h>
15 #include <linux/slab.h>
16 #include <linux/uaccess.h>
17
18 #include <asm/machdep.h>
19 #include <asm/firmware.h>
20 #include <asm/opal.h>
21 #include <asm/debugfs.h>
22 #include <asm/prom.h>
23
24 static u64 opal_scom_unmangle(u64 addr)
25 {
26 u64 tmp;
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 tmp = addr;
48 tmp &= 0x0f00000000000000;
49 addr &= 0xf0ffffffffffffff;
50 addr |= tmp << 4;
51
52 return addr;
53 }
54
55 static int opal_scom_read(uint32_t chip, uint64_t addr, u64 reg, u64 *value)
56 {
57 int64_t rc;
58 __be64 v;
59
60 reg = opal_scom_unmangle(addr + reg);
61 rc = opal_xscom_read(chip, reg, (__be64 *)__pa(&v));
62 if (rc) {
63 *value = 0xfffffffffffffffful;
64 return -EIO;
65 }
66 *value = be64_to_cpu(v);
67 return 0;
68 }
69
70 static int opal_scom_write(uint32_t chip, uint64_t addr, u64 reg, u64 value)
71 {
72 int64_t rc;
73
74 reg = opal_scom_unmangle(addr + reg);
75 rc = opal_xscom_write(chip, reg, value);
76 if (rc)
77 return -EIO;
78 return 0;
79 }
80
81 struct scom_debug_entry {
82 u32 chip;
83 struct debugfs_blob_wrapper path;
84 char name[16];
85 };
86
87 static ssize_t scom_debug_read(struct file *filp, char __user *ubuf,
88 size_t count, loff_t *ppos)
89 {
90 struct scom_debug_entry *ent = filp->private_data;
91 u64 __user *ubuf64 = (u64 __user *)ubuf;
92 loff_t off = *ppos;
93 ssize_t done = 0;
94 u64 reg, reg_base, reg_cnt, val;
95 int rc;
96
97 if (off < 0 || (off & 7) || (count & 7))
98 return -EINVAL;
99 reg_base = off >> 3;
100 reg_cnt = count >> 3;
101
102 for (reg = 0; reg < reg_cnt; reg++) {
103 rc = opal_scom_read(ent->chip, reg_base, reg, &val);
104 if (!rc)
105 rc = put_user(val, ubuf64);
106 if (rc) {
107 if (!done)
108 done = rc;
109 break;
110 }
111 ubuf64++;
112 *ppos += 8;
113 done += 8;
114 }
115 return done;
116 }
117
118 static ssize_t scom_debug_write(struct file *filp, const char __user *ubuf,
119 size_t count, loff_t *ppos)
120 {
121 struct scom_debug_entry *ent = filp->private_data;
122 u64 __user *ubuf64 = (u64 __user *)ubuf;
123 loff_t off = *ppos;
124 ssize_t done = 0;
125 u64 reg, reg_base, reg_cnt, val;
126 int rc;
127
128 if (off < 0 || (off & 7) || (count & 7))
129 return -EINVAL;
130 reg_base = off >> 3;
131 reg_cnt = count >> 3;
132
133 for (reg = 0; reg < reg_cnt; reg++) {
134 rc = get_user(val, ubuf64);
135 if (!rc)
136 rc = opal_scom_write(ent->chip, reg_base, reg, val);
137 if (rc) {
138 if (!done)
139 done = rc;
140 break;
141 }
142 ubuf64++;
143 done += 8;
144 }
145 return done;
146 }
147
148 static const struct file_operations scom_debug_fops = {
149 .read = scom_debug_read,
150 .write = scom_debug_write,
151 .open = simple_open,
152 .llseek = default_llseek,
153 };
154
155 static int scom_debug_init_one(struct dentry *root, struct device_node *dn,
156 int chip)
157 {
158 struct scom_debug_entry *ent;
159 struct dentry *dir;
160
161 ent = kzalloc(sizeof(*ent), GFP_KERNEL);
162 if (!ent)
163 return -ENOMEM;
164
165 ent->chip = chip;
166 snprintf(ent->name, 16, "%08x", chip);
167 ent->path.data = (void *)kasprintf(GFP_KERNEL, "%pOF", dn);
168 ent->path.size = strlen((char *)ent->path.data);
169
170 dir = debugfs_create_dir(ent->name, root);
171 if (!dir) {
172 kfree(ent->path.data);
173 kfree(ent);
174 return -1;
175 }
176
177 debugfs_create_blob("devspec", 0400, dir, &ent->path);
178 debugfs_create_file("access", 0600, dir, ent, &scom_debug_fops);
179
180 return 0;
181 }
182
183 static int scom_debug_init(void)
184 {
185 struct device_node *dn;
186 struct dentry *root;
187 int chip, rc;
188
189 if (!firmware_has_feature(FW_FEATURE_OPAL))
190 return 0;
191
192 root = debugfs_create_dir("scom", powerpc_debugfs_root);
193 if (!root)
194 return -1;
195
196 rc = 0;
197 for_each_node_with_property(dn, "scom-controller") {
198 chip = of_get_ibm_chip_id(dn);
199 WARN_ON(chip == -1);
200 rc |= scom_debug_init_one(root, dn, chip);
201 }
202
203 return rc;
204 }
205 device_initcall(scom_debug_init);