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