powerpc/BSR: add 4096 byte BSR size
[safe/jmp/linux-2.6] / drivers / char / bsr.c
1 /* IBM POWER Barrier Synchronization Register Driver
2  *
3  * Copyright IBM Corporation 2008
4  *
5  * Author: Sonny Rao <sonnyrao@us.ibm.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
20  */
21
22 #include <linux/kernel.h>
23 #include <linux/of.h>
24 #include <linux/of_device.h>
25 #include <linux/of_platform.h>
26 #include <linux/module.h>
27 #include <linux/cdev.h>
28 #include <linux/list.h>
29 #include <linux/mm.h>
30 #include <asm/io.h>
31
32 /*
33  This driver exposes a special register which can be used for fast
34  synchronization across a large SMP machine.  The hardware is exposed
35  as an array of bytes where each process will write to one of the bytes to
36  indicate it has finished the current stage and this update is broadcast to
37  all processors without having to bounce a cacheline between them. In
38  POWER5 and POWER6 there is one of these registers per SMP,  but it is
39  presented in two forms; first, it is given as a whole and then as a number
40  of smaller registers which alias to parts of the single whole register.
41  This can potentially allow multiple groups of processes to each have their
42  own private synchronization device.
43
44  Note that this hardware *must* be written to using *only* single byte writes.
45  It may be read using 1, 2, 4, or 8 byte loads which must be aligned since
46  this region is treated as cache-inhibited  processes should also use a
47  full sync before and after writing to the BSR to ensure all stores and
48  the BSR update have made it to all chips in the system
49 */
50
51 /* This is arbitrary number, up to Power6 it's been 17 or fewer  */
52 #define BSR_MAX_DEVS (32)
53
54 struct bsr_dev {
55         u64      bsr_addr;     /* Real address */
56         u64      bsr_len;      /* length of mem region we can map */
57         unsigned bsr_bytes;    /* size of the BSR reg itself */
58         unsigned bsr_stride;   /* interval at which BSR repeats in the page */
59         unsigned bsr_type;     /* maps to enum below */
60         unsigned bsr_num;      /* bsr id number for its type */
61         int      bsr_minor;
62
63         struct list_head bsr_list;
64
65         dev_t    bsr_dev;
66         struct cdev bsr_cdev;
67         struct device *bsr_device;
68         char     bsr_name[32];
69
70 };
71
72 static unsigned total_bsr_devs;
73 static struct list_head bsr_devs = LIST_HEAD_INIT(bsr_devs);
74 static struct class *bsr_class;
75 static int bsr_major;
76
77 enum {
78         BSR_8    = 0,
79         BSR_16   = 1,
80         BSR_64   = 2,
81         BSR_128  = 3,
82         BSR_4096 = 4,
83         BSR_UNKNOWN = 5,
84         BSR_MAX  = 6,
85 };
86
87 static unsigned bsr_types[BSR_MAX];
88
89 static ssize_t
90 bsr_size_show(struct device *dev, struct device_attribute *attr, char *buf)
91 {
92         struct bsr_dev *bsr_dev = dev_get_drvdata(dev);
93         return sprintf(buf, "%u\n", bsr_dev->bsr_bytes);
94 }
95
96 static ssize_t
97 bsr_stride_show(struct device *dev, struct device_attribute *attr, char *buf)
98 {
99         struct bsr_dev *bsr_dev = dev_get_drvdata(dev);
100         return sprintf(buf, "%u\n", bsr_dev->bsr_stride);
101 }
102
103 static ssize_t
104 bsr_len_show(struct device *dev, struct device_attribute *attr, char *buf)
105 {
106         struct bsr_dev *bsr_dev = dev_get_drvdata(dev);
107         return sprintf(buf, "%llu\n", bsr_dev->bsr_len);
108 }
109
110 static struct device_attribute bsr_dev_attrs[] = {
111         __ATTR(bsr_size, S_IRUGO, bsr_size_show, NULL),
112         __ATTR(bsr_stride, S_IRUGO, bsr_stride_show, NULL),
113         __ATTR(bsr_length, S_IRUGO, bsr_len_show, NULL),
114         __ATTR_NULL
115 };
116
117 static int bsr_mmap(struct file *filp, struct vm_area_struct *vma)
118 {
119         unsigned long size   = vma->vm_end - vma->vm_start;
120         struct bsr_dev *dev = filp->private_data;
121
122         if (size > dev->bsr_len || (size & (PAGE_SIZE-1)))
123                 return -EINVAL;
124
125         vma->vm_flags |= (VM_IO | VM_DONTEXPAND);
126         vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
127
128         if (io_remap_pfn_range(vma, vma->vm_start, dev->bsr_addr >> PAGE_SHIFT,
129                                size, vma->vm_page_prot))
130                 return -EAGAIN;
131
132         return 0;
133 }
134
135 static int bsr_open(struct inode * inode, struct file * filp)
136 {
137         struct cdev *cdev = inode->i_cdev;
138         struct bsr_dev *dev = container_of(cdev, struct bsr_dev, bsr_cdev);
139
140         filp->private_data = dev;
141         return 0;
142 }
143
144 static const struct file_operations bsr_fops = {
145         .owner = THIS_MODULE,
146         .mmap  = bsr_mmap,
147         .open  = bsr_open,
148 };
149
150 static void bsr_cleanup_devs(void)
151 {
152         struct bsr_dev *cur, *n;
153
154         list_for_each_entry_safe(cur, n, &bsr_devs, bsr_list) {
155                 if (cur->bsr_device) {
156                         cdev_del(&cur->bsr_cdev);
157                         device_del(cur->bsr_device);
158                 }
159                 list_del(&cur->bsr_list);
160                 kfree(cur);
161         }
162 }
163
164 static int bsr_add_node(struct device_node *bn)
165 {
166         int bsr_stride_len, bsr_bytes_len, num_bsr_devs;
167         const u32 *bsr_stride;
168         const u32 *bsr_bytes;
169         unsigned i;
170         int ret = -ENODEV;
171
172         bsr_stride = of_get_property(bn, "ibm,lock-stride", &bsr_stride_len);
173         bsr_bytes  = of_get_property(bn, "ibm,#lock-bytes", &bsr_bytes_len);
174
175         if (!bsr_stride || !bsr_bytes ||
176             (bsr_stride_len != bsr_bytes_len)) {
177                 printk(KERN_ERR "bsr of-node has missing/incorrect property\n");
178                 return ret;
179         }
180
181         num_bsr_devs = bsr_bytes_len / sizeof(u32);
182
183         for (i = 0 ; i < num_bsr_devs; i++) {
184                 struct bsr_dev *cur = kzalloc(sizeof(struct bsr_dev),
185                                               GFP_KERNEL);
186                 struct resource res;
187                 int result;
188
189                 if (!cur) {
190                         printk(KERN_ERR "Unable to alloc bsr dev\n");
191                         ret = -ENOMEM;
192                         goto out_err;
193                 }
194
195                 result = of_address_to_resource(bn, i, &res);
196                 if (result < 0) {
197                         printk(KERN_ERR "bsr of-node has invalid reg property, skipping\n");
198                         kfree(cur);
199                         continue;
200                 }
201
202                 cur->bsr_minor  = i + total_bsr_devs;
203                 cur->bsr_addr   = res.start;
204                 cur->bsr_len    = res.end - res.start + 1;
205                 cur->bsr_bytes  = bsr_bytes[i];
206                 cur->bsr_stride = bsr_stride[i];
207                 cur->bsr_dev    = MKDEV(bsr_major, i + total_bsr_devs);
208
209                 switch(cur->bsr_bytes) {
210                 case 8:
211                         cur->bsr_type = BSR_8;
212                         break;
213                 case 16:
214                         cur->bsr_type = BSR_16;
215                         break;
216                 case 64:
217                         cur->bsr_type = BSR_64;
218                         break;
219                 case 128:
220                         cur->bsr_type = BSR_128;
221                         break;
222                 case 4096:
223                         cur->bsr_type = BSR_4096;
224                         break;
225                 default:
226                         cur->bsr_type = BSR_UNKNOWN;
227                 }
228
229                 cur->bsr_num = bsr_types[cur->bsr_type];
230                 snprintf(cur->bsr_name, 32, "bsr%d_%d",
231                          cur->bsr_bytes, cur->bsr_num);
232
233                 cdev_init(&cur->bsr_cdev, &bsr_fops);
234                 result = cdev_add(&cur->bsr_cdev, cur->bsr_dev, 1);
235                 if (result) {
236                         kfree(cur);
237                         goto out_err;
238                 }
239
240                 cur->bsr_device = device_create(bsr_class, NULL, cur->bsr_dev,
241                                                 cur, cur->bsr_name);
242                 if (!cur->bsr_device) {
243                         printk(KERN_ERR "device_create failed for %s\n",
244                                cur->bsr_name);
245                         cdev_del(&cur->bsr_cdev);
246                         kfree(cur);
247                         goto out_err;
248                 }
249
250                 bsr_types[cur->bsr_type] = cur->bsr_num + 1;
251                 list_add_tail(&cur->bsr_list, &bsr_devs);
252         }
253
254         total_bsr_devs += num_bsr_devs;
255
256         return 0;
257
258  out_err:
259
260         bsr_cleanup_devs();
261         return ret;
262 }
263
264 static int bsr_create_devs(struct device_node *bn)
265 {
266         int ret;
267
268         while (bn) {
269                 ret = bsr_add_node(bn);
270                 if (ret) {
271                         of_node_put(bn);
272                         return ret;
273                 }
274                 bn = of_find_compatible_node(bn, NULL, "ibm,bsr");
275         }
276         return 0;
277 }
278
279 static int __init bsr_init(void)
280 {
281         struct device_node *np;
282         dev_t bsr_dev = MKDEV(bsr_major, 0);
283         int ret = -ENODEV;
284         int result;
285
286         np = of_find_compatible_node(NULL, NULL, "ibm,bsr");
287         if (!np)
288                 goto out_err;
289
290         bsr_class = class_create(THIS_MODULE, "bsr");
291         if (IS_ERR(bsr_class)) {
292                 printk(KERN_ERR "class_create() failed for bsr_class\n");
293                 goto out_err_1;
294         }
295         bsr_class->dev_attrs = bsr_dev_attrs;
296
297         result = alloc_chrdev_region(&bsr_dev, 0, BSR_MAX_DEVS, "bsr");
298         bsr_major = MAJOR(bsr_dev);
299         if (result < 0) {
300                 printk(KERN_ERR "alloc_chrdev_region() failed for bsr\n");
301                 goto out_err_2;
302         }
303
304         if ((ret = bsr_create_devs(np)) < 0) {
305                 np = NULL;
306                 goto out_err_3;
307         }
308
309         return 0;
310
311  out_err_3:
312         unregister_chrdev_region(bsr_dev, BSR_MAX_DEVS);
313
314  out_err_2:
315         class_destroy(bsr_class);
316
317  out_err_1:
318         of_node_put(np);
319
320  out_err:
321
322         return ret;
323 }
324
325 static void __exit  bsr_exit(void)
326 {
327
328         bsr_cleanup_devs();
329
330         if (bsr_class)
331                 class_destroy(bsr_class);
332
333         if (bsr_major)
334                 unregister_chrdev_region(MKDEV(bsr_major, 0), BSR_MAX_DEVS);
335 }
336
337 module_init(bsr_init);
338 module_exit(bsr_exit);
339 MODULE_LICENSE("GPL");
340 MODULE_AUTHOR("Sonny Rao <sonnyrao@us.ibm.com>");