Merge branch 'pipe-exclusive-wakeup'
[linux-2.6-microblaze.git] / drivers / vme / bridges / vme_fake.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Fake VME bridge support.
4  *
5  * This drive provides a fake VME bridge chip, this enables debugging of the
6  * VME framework in the absence of a VME system.
7  *
8  * This driver has to do a number of things in software that would be driven
9  * by hardware if it was available, it will also result in extra overhead at
10  * times when compared with driving actual hardware.
11  *
12  * Author: Martyn Welch <martyn@welches.me.uk>
13  * Copyright (c) 2014 Martyn Welch
14  *
15  * Based on vme_tsi148.c:
16  *
17  * Author: Martyn Welch <martyn.welch@ge.com>
18  * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
19  *
20  * Based on work by Tom Armistead and Ajit Prem
21  * Copyright 2004 Motorola Inc.
22  */
23
24 #include <linux/device.h>
25 #include <linux/errno.h>
26 #include <linux/interrupt.h>
27 #include <linux/module.h>
28 #include <linux/moduleparam.h>
29 #include <linux/slab.h>
30 #include <linux/spinlock.h>
31 #include <linux/types.h>
32 #include <linux/vme.h>
33
34 #include "../vme_bridge.h"
35
36 /*
37  *  Define the number of each that the fake driver supports.
38  */
39 #define FAKE_MAX_MASTER         8       /* Max Master Windows */
40 #define FAKE_MAX_SLAVE          8       /* Max Slave Windows */
41
42 /* Structures to hold information normally held in device registers */
43 struct fake_slave_window {
44         int enabled;
45         unsigned long long vme_base;
46         unsigned long long size;
47         void *buf_base;
48         u32 aspace;
49         u32 cycle;
50 };
51
52 struct fake_master_window {
53         int enabled;
54         unsigned long long vme_base;
55         unsigned long long size;
56         u32 aspace;
57         u32 cycle;
58         u32 dwidth;
59 };
60
61 /* Structure used to hold driver specific information */
62 struct fake_driver {
63         struct vme_bridge *parent;
64         struct fake_slave_window slaves[FAKE_MAX_SLAVE];
65         struct fake_master_window masters[FAKE_MAX_MASTER];
66         u32 lm_enabled;
67         unsigned long long lm_base;
68         u32 lm_aspace;
69         u32 lm_cycle;
70         void (*lm_callback[4])(void *);
71         void *lm_data[4];
72         struct tasklet_struct int_tasklet;
73         int int_level;
74         int int_statid;
75         void *crcsr_kernel;
76         dma_addr_t crcsr_bus;
77         /* Only one VME interrupt can be generated at a time, provide locking */
78         struct mutex vme_int;
79 };
80
81 /* Module parameter */
82 static int geoid;
83
84 static const char driver_name[] = "vme_fake";
85
86 static struct vme_bridge *exit_pointer;
87
88 static struct device *vme_root;
89
90 /*
91  * Calling VME bus interrupt callback if provided.
92  */
93 static void fake_VIRQ_tasklet(unsigned long data)
94 {
95         struct vme_bridge *fake_bridge;
96         struct fake_driver *bridge;
97
98         fake_bridge = (struct vme_bridge *) data;
99         bridge = fake_bridge->driver_priv;
100
101         vme_irq_handler(fake_bridge, bridge->int_level, bridge->int_statid);
102 }
103
104 /*
105  * Configure VME interrupt
106  */
107 static void fake_irq_set(struct vme_bridge *fake_bridge, int level,
108                 int state, int sync)
109 {
110         /* Nothing to do */
111 }
112
113 static void *fake_pci_to_ptr(dma_addr_t addr)
114 {
115         return (void *)(uintptr_t)addr;
116 }
117
118 static dma_addr_t fake_ptr_to_pci(void *addr)
119 {
120         return (dma_addr_t)(uintptr_t)addr;
121 }
122
123 /*
124  * Generate a VME bus interrupt at the requested level & vector. Wait for
125  * interrupt to be acked.
126  */
127 static int fake_irq_generate(struct vme_bridge *fake_bridge, int level,
128                 int statid)
129 {
130         struct fake_driver *bridge;
131
132         bridge = fake_bridge->driver_priv;
133
134         mutex_lock(&bridge->vme_int);
135
136         bridge->int_level = level;
137
138         bridge->int_statid = statid;
139
140         /*
141          * Schedule tasklet to run VME handler to emulate normal VME interrupt
142          * handler behaviour.
143          */
144         tasklet_schedule(&bridge->int_tasklet);
145
146         mutex_unlock(&bridge->vme_int);
147
148         return 0;
149 }
150
151 /*
152  * Initialize a slave window with the requested attributes.
153  */
154 static int fake_slave_set(struct vme_slave_resource *image, int enabled,
155                 unsigned long long vme_base, unsigned long long size,
156                 dma_addr_t buf_base, u32 aspace, u32 cycle)
157 {
158         unsigned int i, granularity = 0;
159         unsigned long long vme_bound;
160         struct vme_bridge *fake_bridge;
161         struct fake_driver *bridge;
162
163         fake_bridge = image->parent;
164         bridge = fake_bridge->driver_priv;
165
166         i = image->number;
167
168         switch (aspace) {
169         case VME_A16:
170                 granularity = 0x10;
171                 break;
172         case VME_A24:
173                 granularity = 0x1000;
174                 break;
175         case VME_A32:
176                 granularity = 0x10000;
177                 break;
178         case VME_A64:
179                 granularity = 0x10000;
180                 break;
181         case VME_CRCSR:
182         case VME_USER1:
183         case VME_USER2:
184         case VME_USER3:
185         case VME_USER4:
186         default:
187                 pr_err("Invalid address space\n");
188                 return -EINVAL;
189         }
190
191         /*
192          * Bound address is a valid address for the window, adjust
193          * accordingly
194          */
195         vme_bound = vme_base + size - granularity;
196
197         if (vme_base & (granularity - 1)) {
198                 pr_err("Invalid VME base alignment\n");
199                 return -EINVAL;
200         }
201         if (vme_bound & (granularity - 1)) {
202                 pr_err("Invalid VME bound alignment\n");
203                 return -EINVAL;
204         }
205
206         mutex_lock(&image->mtx);
207
208         bridge->slaves[i].enabled = enabled;
209         bridge->slaves[i].vme_base = vme_base;
210         bridge->slaves[i].size = size;
211         bridge->slaves[i].buf_base = fake_pci_to_ptr(buf_base);
212         bridge->slaves[i].aspace = aspace;
213         bridge->slaves[i].cycle = cycle;
214
215         mutex_unlock(&image->mtx);
216
217         return 0;
218 }
219
220 /*
221  * Get slave window configuration.
222  */
223 static int fake_slave_get(struct vme_slave_resource *image, int *enabled,
224                 unsigned long long *vme_base, unsigned long long *size,
225                 dma_addr_t *buf_base, u32 *aspace, u32 *cycle)
226 {
227         unsigned int i;
228         struct fake_driver *bridge;
229
230         bridge = image->parent->driver_priv;
231
232         i = image->number;
233
234         mutex_lock(&image->mtx);
235
236         *enabled = bridge->slaves[i].enabled;
237         *vme_base = bridge->slaves[i].vme_base;
238         *size = bridge->slaves[i].size;
239         *buf_base = fake_ptr_to_pci(bridge->slaves[i].buf_base);
240         *aspace = bridge->slaves[i].aspace;
241         *cycle = bridge->slaves[i].cycle;
242
243         mutex_unlock(&image->mtx);
244
245         return 0;
246 }
247
248 /*
249  * Set the attributes of an outbound window.
250  */
251 static int fake_master_set(struct vme_master_resource *image, int enabled,
252                 unsigned long long vme_base, unsigned long long size,
253                 u32 aspace, u32 cycle, u32 dwidth)
254 {
255         int retval = 0;
256         unsigned int i;
257         struct vme_bridge *fake_bridge;
258         struct fake_driver *bridge;
259
260         fake_bridge = image->parent;
261
262         bridge = fake_bridge->driver_priv;
263
264         /* Verify input data */
265         if (vme_base & 0xFFFF) {
266                 pr_err("Invalid VME Window alignment\n");
267                 retval = -EINVAL;
268                 goto err_window;
269         }
270
271         if (size & 0xFFFF) {
272                 pr_err("Invalid size alignment\n");
273                 retval = -EINVAL;
274                 goto err_window;
275         }
276
277         if ((size == 0) && (enabled != 0)) {
278                 pr_err("Size must be non-zero for enabled windows\n");
279                 retval = -EINVAL;
280                 goto err_window;
281         }
282
283         /* Setup data width */
284         switch (dwidth) {
285         case VME_D8:
286         case VME_D16:
287         case VME_D32:
288                 break;
289         default:
290                 pr_err("Invalid data width\n");
291                 retval = -EINVAL;
292                 goto err_dwidth;
293         }
294
295         /* Setup address space */
296         switch (aspace) {
297         case VME_A16:
298         case VME_A24:
299         case VME_A32:
300         case VME_A64:
301         case VME_CRCSR:
302         case VME_USER1:
303         case VME_USER2:
304         case VME_USER3:
305         case VME_USER4:
306                 break;
307         default:
308                 pr_err("Invalid address space\n");
309                 retval = -EINVAL;
310                 goto err_aspace;
311         }
312
313         spin_lock(&image->lock);
314
315         i = image->number;
316
317         bridge->masters[i].enabled = enabled;
318         bridge->masters[i].vme_base = vme_base;
319         bridge->masters[i].size = size;
320         bridge->masters[i].aspace = aspace;
321         bridge->masters[i].cycle = cycle;
322         bridge->masters[i].dwidth = dwidth;
323
324         spin_unlock(&image->lock);
325
326         return 0;
327
328 err_aspace:
329 err_dwidth:
330 err_window:
331         return retval;
332
333 }
334
335 /*
336  * Set the attributes of an outbound window.
337  */
338 static int __fake_master_get(struct vme_master_resource *image, int *enabled,
339                 unsigned long long *vme_base, unsigned long long *size,
340                 u32 *aspace, u32 *cycle, u32 *dwidth)
341 {
342         unsigned int i;
343         struct fake_driver *bridge;
344
345         bridge = image->parent->driver_priv;
346
347         i = image->number;
348
349         *enabled = bridge->masters[i].enabled;
350         *vme_base = bridge->masters[i].vme_base;
351         *size = bridge->masters[i].size;
352         *aspace = bridge->masters[i].aspace;
353         *cycle = bridge->masters[i].cycle;
354         *dwidth = bridge->masters[i].dwidth;
355
356         return 0;
357 }
358
359
360 static int fake_master_get(struct vme_master_resource *image, int *enabled,
361                 unsigned long long *vme_base, unsigned long long *size,
362                 u32 *aspace, u32 *cycle, u32 *dwidth)
363 {
364         int retval;
365
366         spin_lock(&image->lock);
367
368         retval = __fake_master_get(image, enabled, vme_base, size, aspace,
369                         cycle, dwidth);
370
371         spin_unlock(&image->lock);
372
373         return retval;
374 }
375
376
377 static void fake_lm_check(struct fake_driver *bridge, unsigned long long addr,
378                           u32 aspace, u32 cycle)
379 {
380         struct vme_bridge *fake_bridge;
381         unsigned long long lm_base;
382         u32 lm_aspace, lm_cycle;
383         int i;
384         struct vme_lm_resource *lm;
385         struct list_head *pos = NULL, *n;
386
387         /* Get vme_bridge */
388         fake_bridge = bridge->parent;
389
390         /* Loop through each location monitor resource */
391         list_for_each_safe(pos, n, &fake_bridge->lm_resources) {
392                 lm = list_entry(pos, struct vme_lm_resource, list);
393
394                 /* If disabled, we're done */
395                 if (bridge->lm_enabled == 0)
396                         return;
397
398                 lm_base = bridge->lm_base;
399                 lm_aspace = bridge->lm_aspace;
400                 lm_cycle = bridge->lm_cycle;
401
402                 /* First make sure that the cycle and address space match */
403                 if ((lm_aspace == aspace) && (lm_cycle == cycle)) {
404                         for (i = 0; i < lm->monitors; i++) {
405                                 /* Each location monitor covers 8 bytes */
406                                 if (((lm_base + (8 * i)) <= addr) &&
407                                     ((lm_base + (8 * i) + 8) > addr)) {
408                                         if (bridge->lm_callback[i])
409                                                 bridge->lm_callback[i](
410                                                         bridge->lm_data[i]);
411                                 }
412                         }
413                 }
414         }
415 }
416
417 static noinline_for_stack u8 fake_vmeread8(struct fake_driver *bridge,
418                                            unsigned long long addr,
419                                            u32 aspace, u32 cycle)
420 {
421         u8 retval = 0xff;
422         int i;
423         unsigned long long start, end, offset;
424         u8 *loc;
425
426         for (i = 0; i < FAKE_MAX_SLAVE; i++) {
427                 start = bridge->slaves[i].vme_base;
428                 end = bridge->slaves[i].vme_base + bridge->slaves[i].size;
429
430                 if (aspace != bridge->slaves[i].aspace)
431                         continue;
432
433                 if (cycle != bridge->slaves[i].cycle)
434                         continue;
435
436                 if ((addr >= start) && (addr < end)) {
437                         offset = addr - bridge->slaves[i].vme_base;
438                         loc = (u8 *)(bridge->slaves[i].buf_base + offset);
439                         retval = *loc;
440
441                         break;
442                 }
443         }
444
445         fake_lm_check(bridge, addr, aspace, cycle);
446
447         return retval;
448 }
449
450 static noinline_for_stack u16 fake_vmeread16(struct fake_driver *bridge,
451                                              unsigned long long addr,
452                                              u32 aspace, u32 cycle)
453 {
454         u16 retval = 0xffff;
455         int i;
456         unsigned long long start, end, offset;
457         u16 *loc;
458
459         for (i = 0; i < FAKE_MAX_SLAVE; i++) {
460                 if (aspace != bridge->slaves[i].aspace)
461                         continue;
462
463                 if (cycle != bridge->slaves[i].cycle)
464                         continue;
465
466                 start = bridge->slaves[i].vme_base;
467                 end = bridge->slaves[i].vme_base + bridge->slaves[i].size;
468
469                 if ((addr >= start) && ((addr + 1) < end)) {
470                         offset = addr - bridge->slaves[i].vme_base;
471                         loc = (u16 *)(bridge->slaves[i].buf_base + offset);
472                         retval = *loc;
473
474                         break;
475                 }
476         }
477
478         fake_lm_check(bridge, addr, aspace, cycle);
479
480         return retval;
481 }
482
483 static noinline_for_stack u32 fake_vmeread32(struct fake_driver *bridge,
484                                              unsigned long long addr,
485                                              u32 aspace, u32 cycle)
486 {
487         u32 retval = 0xffffffff;
488         int i;
489         unsigned long long start, end, offset;
490         u32 *loc;
491
492         for (i = 0; i < FAKE_MAX_SLAVE; i++) {
493                 if (aspace != bridge->slaves[i].aspace)
494                         continue;
495
496                 if (cycle != bridge->slaves[i].cycle)
497                         continue;
498
499                 start = bridge->slaves[i].vme_base;
500                 end = bridge->slaves[i].vme_base + bridge->slaves[i].size;
501
502                 if ((addr >= start) && ((addr + 3) < end)) {
503                         offset = addr - bridge->slaves[i].vme_base;
504                         loc = (u32 *)(bridge->slaves[i].buf_base + offset);
505                         retval = *loc;
506
507                         break;
508                 }
509         }
510
511         fake_lm_check(bridge, addr, aspace, cycle);
512
513         return retval;
514 }
515
516 static ssize_t fake_master_read(struct vme_master_resource *image, void *buf,
517                 size_t count, loff_t offset)
518 {
519         int retval;
520         u32 aspace, cycle, dwidth;
521         struct vme_bridge *fake_bridge;
522         struct fake_driver *priv;
523         int i;
524         unsigned long long addr;
525         unsigned int done = 0;
526         unsigned int count32;
527
528         fake_bridge = image->parent;
529
530         priv = fake_bridge->driver_priv;
531
532         i = image->number;
533
534         addr = (unsigned long long)priv->masters[i].vme_base + offset;
535         aspace = priv->masters[i].aspace;
536         cycle = priv->masters[i].cycle;
537         dwidth = priv->masters[i].dwidth;
538
539         spin_lock(&image->lock);
540
541         /* The following code handles VME address alignment. We cannot use
542          * memcpy_xxx here because it may cut data transfers in to 8-bit
543          * cycles when D16 or D32 cycles are required on the VME bus.
544          * On the other hand, the bridge itself assures that the maximum data
545          * cycle configured for the transfer is used and splits it
546          * automatically for non-aligned addresses, so we don't want the
547          * overhead of needlessly forcing small transfers for the entire cycle.
548          */
549         if (addr & 0x1) {
550                 *(u8 *)buf = fake_vmeread8(priv, addr, aspace, cycle);
551                 done += 1;
552                 if (done == count)
553                         goto out;
554         }
555         if ((dwidth == VME_D16) || (dwidth == VME_D32)) {
556                 if ((addr + done) & 0x2) {
557                         if ((count - done) < 2) {
558                                 *(u8 *)(buf + done) = fake_vmeread8(priv,
559                                                 addr + done, aspace, cycle);
560                                 done += 1;
561                                 goto out;
562                         } else {
563                                 *(u16 *)(buf + done) = fake_vmeread16(priv,
564                                                 addr + done, aspace, cycle);
565                                 done += 2;
566                         }
567                 }
568         }
569
570         if (dwidth == VME_D32) {
571                 count32 = (count - done) & ~0x3;
572                 while (done < count32) {
573                         *(u32 *)(buf + done) = fake_vmeread32(priv, addr + done,
574                                         aspace, cycle);
575                         done += 4;
576                 }
577         } else if (dwidth == VME_D16) {
578                 count32 = (count - done) & ~0x3;
579                 while (done < count32) {
580                         *(u16 *)(buf + done) = fake_vmeread16(priv, addr + done,
581                                         aspace, cycle);
582                         done += 2;
583                 }
584         } else if (dwidth == VME_D8) {
585                 count32 = (count - done);
586                 while (done < count32) {
587                         *(u8 *)(buf + done) = fake_vmeread8(priv, addr + done,
588                                         aspace, cycle);
589                         done += 1;
590                 }
591
592         }
593
594         if ((dwidth == VME_D16) || (dwidth == VME_D32)) {
595                 if ((count - done) & 0x2) {
596                         *(u16 *)(buf + done) = fake_vmeread16(priv, addr + done,
597                                         aspace, cycle);
598                         done += 2;
599                 }
600         }
601         if ((count - done) & 0x1) {
602                 *(u8 *)(buf + done) = fake_vmeread8(priv, addr + done, aspace,
603                                 cycle);
604                 done += 1;
605         }
606
607 out:
608         retval = count;
609
610         spin_unlock(&image->lock);
611
612         return retval;
613 }
614
615 static noinline_for_stack void fake_vmewrite8(struct fake_driver *bridge,
616                                               u8 *buf, unsigned long long addr,
617                                               u32 aspace, u32 cycle)
618 {
619         int i;
620         unsigned long long start, end, offset;
621         u8 *loc;
622
623         for (i = 0; i < FAKE_MAX_SLAVE; i++) {
624                 if (aspace != bridge->slaves[i].aspace)
625                         continue;
626
627                 if (cycle != bridge->slaves[i].cycle)
628                         continue;
629
630                 start = bridge->slaves[i].vme_base;
631                 end = bridge->slaves[i].vme_base + bridge->slaves[i].size;
632
633                 if ((addr >= start) && (addr < end)) {
634                         offset = addr - bridge->slaves[i].vme_base;
635                         loc = (u8 *)((void *)bridge->slaves[i].buf_base + offset);
636                         *loc = *buf;
637
638                         break;
639                 }
640         }
641
642         fake_lm_check(bridge, addr, aspace, cycle);
643
644 }
645
646 static noinline_for_stack void fake_vmewrite16(struct fake_driver *bridge,
647                                                u16 *buf, unsigned long long addr,
648                                                u32 aspace, u32 cycle)
649 {
650         int i;
651         unsigned long long start, end, offset;
652         u16 *loc;
653
654         for (i = 0; i < FAKE_MAX_SLAVE; i++) {
655                 if (aspace != bridge->slaves[i].aspace)
656                         continue;
657
658                 if (cycle != bridge->slaves[i].cycle)
659                         continue;
660
661                 start = bridge->slaves[i].vme_base;
662                 end = bridge->slaves[i].vme_base + bridge->slaves[i].size;
663
664                 if ((addr >= start) && ((addr + 1) < end)) {
665                         offset = addr - bridge->slaves[i].vme_base;
666                         loc = (u16 *)((void *)bridge->slaves[i].buf_base + offset);
667                         *loc = *buf;
668
669                         break;
670                 }
671         }
672
673         fake_lm_check(bridge, addr, aspace, cycle);
674
675 }
676
677 static noinline_for_stack void fake_vmewrite32(struct fake_driver *bridge,
678                                                u32 *buf, unsigned long long addr,
679                                                u32 aspace, u32 cycle)
680 {
681         int i;
682         unsigned long long start, end, offset;
683         u32 *loc;
684
685         for (i = 0; i < FAKE_MAX_SLAVE; i++) {
686                 if (aspace != bridge->slaves[i].aspace)
687                         continue;
688
689                 if (cycle != bridge->slaves[i].cycle)
690                         continue;
691
692                 start = bridge->slaves[i].vme_base;
693                 end = bridge->slaves[i].vme_base + bridge->slaves[i].size;
694
695                 if ((addr >= start) && ((addr + 3) < end)) {
696                         offset = addr - bridge->slaves[i].vme_base;
697                         loc = (u32 *)((void *)bridge->slaves[i].buf_base + offset);
698                         *loc = *buf;
699
700                         break;
701                 }
702         }
703
704         fake_lm_check(bridge, addr, aspace, cycle);
705
706 }
707
708 static ssize_t fake_master_write(struct vme_master_resource *image, void *buf,
709                 size_t count, loff_t offset)
710 {
711         int retval = 0;
712         u32 aspace, cycle, dwidth;
713         unsigned long long addr;
714         int i;
715         unsigned int done = 0;
716         unsigned int count32;
717
718         struct vme_bridge *fake_bridge;
719         struct fake_driver *bridge;
720
721         fake_bridge = image->parent;
722
723         bridge = fake_bridge->driver_priv;
724
725         i = image->number;
726
727         addr = bridge->masters[i].vme_base + offset;
728         aspace = bridge->masters[i].aspace;
729         cycle = bridge->masters[i].cycle;
730         dwidth = bridge->masters[i].dwidth;
731
732         spin_lock(&image->lock);
733
734         /* Here we apply for the same strategy we do in master_read
735          * function in order to assure the correct cycles.
736          */
737         if (addr & 0x1) {
738                 fake_vmewrite8(bridge, (u8 *)buf, addr, aspace, cycle);
739                 done += 1;
740                 if (done == count)
741                         goto out;
742         }
743
744         if ((dwidth == VME_D16) || (dwidth == VME_D32)) {
745                 if ((addr + done) & 0x2) {
746                         if ((count - done) < 2) {
747                                 fake_vmewrite8(bridge, (u8 *)(buf + done),
748                                                 addr + done, aspace, cycle);
749                                 done += 1;
750                                 goto out;
751                         } else {
752                                 fake_vmewrite16(bridge, (u16 *)(buf + done),
753                                                 addr + done, aspace, cycle);
754                                 done += 2;
755                         }
756                 }
757         }
758
759         if (dwidth == VME_D32) {
760                 count32 = (count - done) & ~0x3;
761                 while (done < count32) {
762                         fake_vmewrite32(bridge, (u32 *)(buf + done),
763                                         addr + done, aspace, cycle);
764                         done += 4;
765                 }
766         } else if (dwidth == VME_D16) {
767                 count32 = (count - done) & ~0x3;
768                 while (done < count32) {
769                         fake_vmewrite16(bridge, (u16 *)(buf + done),
770                                         addr + done, aspace, cycle);
771                         done += 2;
772                 }
773         } else if (dwidth == VME_D8) {
774                 count32 = (count - done);
775                 while (done < count32) {
776                         fake_vmewrite8(bridge, (u8 *)(buf + done), addr + done,
777                                         aspace, cycle);
778                         done += 1;
779                 }
780
781         }
782
783         if ((dwidth == VME_D16) || (dwidth == VME_D32)) {
784                 if ((count - done) & 0x2) {
785                         fake_vmewrite16(bridge, (u16 *)(buf + done),
786                                         addr + done, aspace, cycle);
787                         done += 2;
788                 }
789         }
790
791         if ((count - done) & 0x1) {
792                 fake_vmewrite8(bridge, (u8 *)(buf + done), addr + done, aspace,
793                                 cycle);
794                 done += 1;
795         }
796
797 out:
798         retval = count;
799
800         spin_unlock(&image->lock);
801
802         return retval;
803 }
804
805 /*
806  * Perform an RMW cycle on the VME bus.
807  *
808  * Requires a previously configured master window, returns final value.
809  */
810 static unsigned int fake_master_rmw(struct vme_master_resource *image,
811                 unsigned int mask, unsigned int compare, unsigned int swap,
812                 loff_t offset)
813 {
814         u32 tmp, base;
815         u32 aspace, cycle;
816         int i;
817         struct fake_driver *bridge;
818
819         bridge = image->parent->driver_priv;
820
821         /* Find the PCI address that maps to the desired VME address */
822         i = image->number;
823
824         base = bridge->masters[i].vme_base;
825         aspace = bridge->masters[i].aspace;
826         cycle = bridge->masters[i].cycle;
827
828         /* Lock image */
829         spin_lock(&image->lock);
830
831         /* Read existing value */
832         tmp = fake_vmeread32(bridge, base + offset, aspace, cycle);
833
834         /* Perform check */
835         if ((tmp && mask) == (compare && mask)) {
836                 tmp = tmp | (mask | swap);
837                 tmp = tmp & (~mask | swap);
838
839                 /* Write back */
840                 fake_vmewrite32(bridge, &tmp, base + offset, aspace, cycle);
841         }
842
843         /* Unlock image */
844         spin_unlock(&image->lock);
845
846         return tmp;
847 }
848
849 /*
850  * All 4 location monitors reside at the same base - this is therefore a
851  * system wide configuration.
852  *
853  * This does not enable the LM monitor - that should be done when the first
854  * callback is attached and disabled when the last callback is removed.
855  */
856 static int fake_lm_set(struct vme_lm_resource *lm, unsigned long long lm_base,
857                 u32 aspace, u32 cycle)
858 {
859         int i;
860         struct vme_bridge *fake_bridge;
861         struct fake_driver *bridge;
862
863         fake_bridge = lm->parent;
864
865         bridge = fake_bridge->driver_priv;
866
867         mutex_lock(&lm->mtx);
868
869         /* If we already have a callback attached, we can't move it! */
870         for (i = 0; i < lm->monitors; i++) {
871                 if (bridge->lm_callback[i]) {
872                         mutex_unlock(&lm->mtx);
873                         pr_err("Location monitor callback attached, can't reset\n");
874                         return -EBUSY;
875                 }
876         }
877
878         switch (aspace) {
879         case VME_A16:
880         case VME_A24:
881         case VME_A32:
882         case VME_A64:
883                 break;
884         default:
885                 mutex_unlock(&lm->mtx);
886                 pr_err("Invalid address space\n");
887                 return -EINVAL;
888         }
889
890         bridge->lm_base = lm_base;
891         bridge->lm_aspace = aspace;
892         bridge->lm_cycle = cycle;
893
894         mutex_unlock(&lm->mtx);
895
896         return 0;
897 }
898
899 /* Get configuration of the callback monitor and return whether it is enabled
900  * or disabled.
901  */
902 static int fake_lm_get(struct vme_lm_resource *lm,
903                 unsigned long long *lm_base, u32 *aspace, u32 *cycle)
904 {
905         struct fake_driver *bridge;
906
907         bridge = lm->parent->driver_priv;
908
909         mutex_lock(&lm->mtx);
910
911         *lm_base = bridge->lm_base;
912         *aspace = bridge->lm_aspace;
913         *cycle = bridge->lm_cycle;
914
915         mutex_unlock(&lm->mtx);
916
917         return bridge->lm_enabled;
918 }
919
920 /*
921  * Attach a callback to a specific location monitor.
922  *
923  * Callback will be passed the monitor triggered.
924  */
925 static int fake_lm_attach(struct vme_lm_resource *lm, int monitor,
926                 void (*callback)(void *), void *data)
927 {
928         struct vme_bridge *fake_bridge;
929         struct fake_driver *bridge;
930
931         fake_bridge = lm->parent;
932
933         bridge = fake_bridge->driver_priv;
934
935         mutex_lock(&lm->mtx);
936
937         /* Ensure that the location monitor is configured - need PGM or DATA */
938         if (bridge->lm_cycle == 0) {
939                 mutex_unlock(&lm->mtx);
940                 pr_err("Location monitor not properly configured\n");
941                 return -EINVAL;
942         }
943
944         /* Check that a callback isn't already attached */
945         if (bridge->lm_callback[monitor]) {
946                 mutex_unlock(&lm->mtx);
947                 pr_err("Existing callback attached\n");
948                 return -EBUSY;
949         }
950
951         /* Attach callback */
952         bridge->lm_callback[monitor] = callback;
953         bridge->lm_data[monitor] = data;
954
955         /* Ensure that global Location Monitor Enable set */
956         bridge->lm_enabled = 1;
957
958         mutex_unlock(&lm->mtx);
959
960         return 0;
961 }
962
963 /*
964  * Detach a callback function forn a specific location monitor.
965  */
966 static int fake_lm_detach(struct vme_lm_resource *lm, int monitor)
967 {
968         u32 tmp;
969         int i;
970         struct fake_driver *bridge;
971
972         bridge = lm->parent->driver_priv;
973
974         mutex_lock(&lm->mtx);
975
976         /* Detach callback */
977         bridge->lm_callback[monitor] = NULL;
978         bridge->lm_data[monitor] = NULL;
979
980         /* If all location monitors disabled, disable global Location Monitor */
981         tmp = 0;
982         for (i = 0; i < lm->monitors; i++) {
983                 if (bridge->lm_callback[i])
984                         tmp = 1;
985         }
986
987         if (tmp == 0)
988                 bridge->lm_enabled = 0;
989
990         mutex_unlock(&lm->mtx);
991
992         return 0;
993 }
994
995 /*
996  * Determine Geographical Addressing
997  */
998 static int fake_slot_get(struct vme_bridge *fake_bridge)
999 {
1000         return geoid;
1001 }
1002
1003 static void *fake_alloc_consistent(struct device *parent, size_t size,
1004                 dma_addr_t *dma)
1005 {
1006         void *alloc = kmalloc(size, GFP_KERNEL);
1007
1008         if (alloc)
1009                 *dma = fake_ptr_to_pci(alloc);
1010
1011         return alloc;
1012 }
1013
1014 static void fake_free_consistent(struct device *parent, size_t size,
1015                 void *vaddr, dma_addr_t dma)
1016 {
1017         kfree(vaddr);
1018 /*
1019         dma_free_coherent(parent, size, vaddr, dma);
1020 */
1021 }
1022
1023 /*
1024  * Configure CR/CSR space
1025  *
1026  * Access to the CR/CSR can be configured at power-up. The location of the
1027  * CR/CSR registers in the CR/CSR address space is determined by the boards
1028  * Geographic address.
1029  *
1030  * Each board has a 512kB window, with the highest 4kB being used for the
1031  * boards registers, this means there is a fix length 508kB window which must
1032  * be mapped onto PCI memory.
1033  */
1034 static int fake_crcsr_init(struct vme_bridge *fake_bridge)
1035 {
1036         u32 vstat;
1037         struct fake_driver *bridge;
1038
1039         bridge = fake_bridge->driver_priv;
1040
1041         /* Allocate mem for CR/CSR image */
1042         bridge->crcsr_kernel = kzalloc(VME_CRCSR_BUF_SIZE, GFP_KERNEL);
1043         bridge->crcsr_bus = fake_ptr_to_pci(bridge->crcsr_kernel);
1044         if (!bridge->crcsr_kernel)
1045                 return -ENOMEM;
1046
1047         vstat = fake_slot_get(fake_bridge);
1048
1049         pr_info("CR/CSR Offset: %d\n", vstat);
1050
1051         return 0;
1052 }
1053
1054 static void fake_crcsr_exit(struct vme_bridge *fake_bridge)
1055 {
1056         struct fake_driver *bridge;
1057
1058         bridge = fake_bridge->driver_priv;
1059
1060         kfree(bridge->crcsr_kernel);
1061 }
1062
1063
1064 static int __init fake_init(void)
1065 {
1066         int retval, i;
1067         struct list_head *pos = NULL, *n;
1068         struct vme_bridge *fake_bridge;
1069         struct fake_driver *fake_device;
1070         struct vme_master_resource *master_image;
1071         struct vme_slave_resource *slave_image;
1072         struct vme_lm_resource *lm;
1073
1074         /* We need a fake parent device */
1075         vme_root = __root_device_register("vme", THIS_MODULE);
1076
1077         /* If we want to support more than one bridge at some point, we need to
1078          * dynamically allocate this so we get one per device.
1079          */
1080         fake_bridge = kzalloc(sizeof(*fake_bridge), GFP_KERNEL);
1081         if (!fake_bridge) {
1082                 retval = -ENOMEM;
1083                 goto err_struct;
1084         }
1085
1086         fake_device = kzalloc(sizeof(*fake_device), GFP_KERNEL);
1087         if (!fake_device) {
1088                 retval = -ENOMEM;
1089                 goto err_driver;
1090         }
1091
1092         fake_bridge->driver_priv = fake_device;
1093
1094         fake_bridge->parent = vme_root;
1095
1096         fake_device->parent = fake_bridge;
1097
1098         /* Initialize wait queues & mutual exclusion flags */
1099         mutex_init(&fake_device->vme_int);
1100         mutex_init(&fake_bridge->irq_mtx);
1101         tasklet_init(&fake_device->int_tasklet, fake_VIRQ_tasklet,
1102                         (unsigned long) fake_bridge);
1103
1104         strcpy(fake_bridge->name, driver_name);
1105
1106         /* Add master windows to list */
1107         INIT_LIST_HEAD(&fake_bridge->master_resources);
1108         for (i = 0; i < FAKE_MAX_MASTER; i++) {
1109                 master_image = kmalloc(sizeof(*master_image), GFP_KERNEL);
1110                 if (!master_image) {
1111                         retval = -ENOMEM;
1112                         goto err_master;
1113                 }
1114                 master_image->parent = fake_bridge;
1115                 spin_lock_init(&master_image->lock);
1116                 master_image->locked = 0;
1117                 master_image->number = i;
1118                 master_image->address_attr = VME_A16 | VME_A24 | VME_A32 |
1119                         VME_A64;
1120                 master_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT |
1121                         VME_2eVME | VME_2eSST | VME_2eSSTB | VME_2eSST160 |
1122                         VME_2eSST267 | VME_2eSST320 | VME_SUPER | VME_USER |
1123                         VME_PROG | VME_DATA;
1124                 master_image->width_attr = VME_D16 | VME_D32;
1125                 memset(&master_image->bus_resource, 0,
1126                                 sizeof(struct resource));
1127                 master_image->kern_base  = NULL;
1128                 list_add_tail(&master_image->list,
1129                                 &fake_bridge->master_resources);
1130         }
1131
1132         /* Add slave windows to list */
1133         INIT_LIST_HEAD(&fake_bridge->slave_resources);
1134         for (i = 0; i < FAKE_MAX_SLAVE; i++) {
1135                 slave_image = kmalloc(sizeof(*slave_image), GFP_KERNEL);
1136                 if (!slave_image) {
1137                         retval = -ENOMEM;
1138                         goto err_slave;
1139                 }
1140                 slave_image->parent = fake_bridge;
1141                 mutex_init(&slave_image->mtx);
1142                 slave_image->locked = 0;
1143                 slave_image->number = i;
1144                 slave_image->address_attr = VME_A16 | VME_A24 | VME_A32 |
1145                         VME_A64 | VME_CRCSR | VME_USER1 | VME_USER2 |
1146                         VME_USER3 | VME_USER4;
1147                 slave_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT |
1148                         VME_2eVME | VME_2eSST | VME_2eSSTB | VME_2eSST160 |
1149                         VME_2eSST267 | VME_2eSST320 | VME_SUPER | VME_USER |
1150                         VME_PROG | VME_DATA;
1151                 list_add_tail(&slave_image->list,
1152                                 &fake_bridge->slave_resources);
1153         }
1154
1155         /* Add location monitor to list */
1156         INIT_LIST_HEAD(&fake_bridge->lm_resources);
1157         lm = kmalloc(sizeof(*lm), GFP_KERNEL);
1158         if (!lm) {
1159                 retval = -ENOMEM;
1160                 goto err_lm;
1161         }
1162         lm->parent = fake_bridge;
1163         mutex_init(&lm->mtx);
1164         lm->locked = 0;
1165         lm->number = 1;
1166         lm->monitors = 4;
1167         list_add_tail(&lm->list, &fake_bridge->lm_resources);
1168
1169         fake_bridge->slave_get = fake_slave_get;
1170         fake_bridge->slave_set = fake_slave_set;
1171         fake_bridge->master_get = fake_master_get;
1172         fake_bridge->master_set = fake_master_set;
1173         fake_bridge->master_read = fake_master_read;
1174         fake_bridge->master_write = fake_master_write;
1175         fake_bridge->master_rmw = fake_master_rmw;
1176         fake_bridge->irq_set = fake_irq_set;
1177         fake_bridge->irq_generate = fake_irq_generate;
1178         fake_bridge->lm_set = fake_lm_set;
1179         fake_bridge->lm_get = fake_lm_get;
1180         fake_bridge->lm_attach = fake_lm_attach;
1181         fake_bridge->lm_detach = fake_lm_detach;
1182         fake_bridge->slot_get = fake_slot_get;
1183         fake_bridge->alloc_consistent = fake_alloc_consistent;
1184         fake_bridge->free_consistent = fake_free_consistent;
1185
1186         pr_info("Board is%s the VME system controller\n",
1187                         (geoid == 1) ? "" : " not");
1188
1189         pr_info("VME geographical address is set to %d\n", geoid);
1190
1191         retval = fake_crcsr_init(fake_bridge);
1192         if (retval) {
1193                 pr_err("CR/CSR configuration failed.\n");
1194                 goto err_crcsr;
1195         }
1196
1197         retval = vme_register_bridge(fake_bridge);
1198         if (retval != 0) {
1199                 pr_err("Chip Registration failed.\n");
1200                 goto err_reg;
1201         }
1202
1203         exit_pointer = fake_bridge;
1204
1205         return 0;
1206
1207 err_reg:
1208         fake_crcsr_exit(fake_bridge);
1209 err_crcsr:
1210 err_lm:
1211         /* resources are stored in link list */
1212         list_for_each_safe(pos, n, &fake_bridge->lm_resources) {
1213                 lm = list_entry(pos, struct vme_lm_resource, list);
1214                 list_del(pos);
1215                 kfree(lm);
1216         }
1217 err_slave:
1218         /* resources are stored in link list */
1219         list_for_each_safe(pos, n, &fake_bridge->slave_resources) {
1220                 slave_image = list_entry(pos, struct vme_slave_resource, list);
1221                 list_del(pos);
1222                 kfree(slave_image);
1223         }
1224 err_master:
1225         /* resources are stored in link list */
1226         list_for_each_safe(pos, n, &fake_bridge->master_resources) {
1227                 master_image = list_entry(pos, struct vme_master_resource,
1228                                 list);
1229                 list_del(pos);
1230                 kfree(master_image);
1231         }
1232
1233         kfree(fake_device);
1234 err_driver:
1235         kfree(fake_bridge);
1236 err_struct:
1237         return retval;
1238
1239 }
1240
1241
1242 static void __exit fake_exit(void)
1243 {
1244         struct list_head *pos = NULL;
1245         struct list_head *tmplist;
1246         struct vme_master_resource *master_image;
1247         struct vme_slave_resource *slave_image;
1248         int i;
1249         struct vme_bridge *fake_bridge;
1250         struct fake_driver *bridge;
1251
1252         fake_bridge = exit_pointer;
1253
1254         bridge = fake_bridge->driver_priv;
1255
1256         pr_debug("Driver is being unloaded.\n");
1257
1258         /*
1259          *  Shutdown all inbound and outbound windows.
1260          */
1261         for (i = 0; i < FAKE_MAX_MASTER; i++)
1262                 bridge->masters[i].enabled = 0;
1263
1264         for (i = 0; i < FAKE_MAX_SLAVE; i++)
1265                 bridge->slaves[i].enabled = 0;
1266
1267         /*
1268          *  Shutdown Location monitor.
1269          */
1270         bridge->lm_enabled = 0;
1271
1272         vme_unregister_bridge(fake_bridge);
1273
1274         fake_crcsr_exit(fake_bridge);
1275         /* resources are stored in link list */
1276         list_for_each_safe(pos, tmplist, &fake_bridge->slave_resources) {
1277                 slave_image = list_entry(pos, struct vme_slave_resource, list);
1278                 list_del(pos);
1279                 kfree(slave_image);
1280         }
1281
1282         /* resources are stored in link list */
1283         list_for_each_safe(pos, tmplist, &fake_bridge->master_resources) {
1284                 master_image = list_entry(pos, struct vme_master_resource,
1285                                 list);
1286                 list_del(pos);
1287                 kfree(master_image);
1288         }
1289
1290         kfree(fake_bridge->driver_priv);
1291
1292         kfree(fake_bridge);
1293
1294         root_device_unregister(vme_root);
1295 }
1296
1297
1298 MODULE_PARM_DESC(geoid, "Set geographical addressing");
1299 module_param(geoid, int, 0);
1300
1301 MODULE_DESCRIPTION("Fake VME bridge driver");
1302 MODULE_LICENSE("GPL");
1303
1304 module_init(fake_init);
1305 module_exit(fake_exit);