1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Fake VME bridge support.
5 * This drive provides a fake VME bridge chip, this enables debugging of the
6 * VME framework in the absence of a VME system.
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.
12 * Author: Martyn Welch <martyn@welches.me.uk>
13 * Copyright (c) 2014 Martyn Welch
15 * Based on vme_tsi148.c:
17 * Author: Martyn Welch <martyn.welch@ge.com>
18 * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
20 * Based on work by Tom Armistead and Ajit Prem
21 * Copyright 2004 Motorola Inc.
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>
34 #include "../vme_bridge.h"
37 * Define the number of each that the fake driver supports.
39 #define FAKE_MAX_MASTER 8 /* Max Master Windows */
40 #define FAKE_MAX_SLAVE 8 /* Max Slave Windows */
42 /* Structures to hold information normally held in device registers */
43 struct fake_slave_window
{
45 unsigned long long vme_base
;
46 unsigned long long size
;
52 struct fake_master_window
{
54 unsigned long long vme_base
;
55 unsigned long long size
;
61 /* Structure used to hold driver specific information */
63 struct vme_bridge
*parent
;
64 struct fake_slave_window slaves
[FAKE_MAX_SLAVE
];
65 struct fake_master_window masters
[FAKE_MAX_MASTER
];
67 unsigned long long lm_base
;
70 void (*lm_callback
[4])(void *);
72 struct tasklet_struct int_tasklet
;
77 /* Only one VME interrupt can be generated at a time, provide locking */
81 /* Module parameter */
84 static const char driver_name
[] = "vme_fake";
86 static struct vme_bridge
*exit_pointer
;
88 static struct device
*vme_root
;
91 * Calling VME bus interrupt callback if provided.
93 static void fake_VIRQ_tasklet(unsigned long data
)
95 struct vme_bridge
*fake_bridge
;
96 struct fake_driver
*bridge
;
98 fake_bridge
= (struct vme_bridge
*) data
;
99 bridge
= fake_bridge
->driver_priv
;
101 vme_irq_handler(fake_bridge
, bridge
->int_level
, bridge
->int_statid
);
105 * Configure VME interrupt
107 static void fake_irq_set(struct vme_bridge
*fake_bridge
, int level
,
113 static void *fake_pci_to_ptr(dma_addr_t addr
)
115 return (void *)(uintptr_t)addr
;
118 static dma_addr_t
fake_ptr_to_pci(void *addr
)
120 return (dma_addr_t
)(uintptr_t)addr
;
124 * Generate a VME bus interrupt at the requested level & vector. Wait for
125 * interrupt to be acked.
127 static int fake_irq_generate(struct vme_bridge
*fake_bridge
, int level
,
130 struct fake_driver
*bridge
;
132 bridge
= fake_bridge
->driver_priv
;
134 mutex_lock(&bridge
->vme_int
);
136 bridge
->int_level
= level
;
138 bridge
->int_statid
= statid
;
141 * Schedule tasklet to run VME handler to emulate normal VME interrupt
144 tasklet_schedule(&bridge
->int_tasklet
);
146 mutex_unlock(&bridge
->vme_int
);
152 * Initialize a slave window with the requested attributes.
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
)
158 unsigned int i
, granularity
= 0;
159 unsigned long long vme_bound
;
160 struct vme_bridge
*fake_bridge
;
161 struct fake_driver
*bridge
;
163 fake_bridge
= image
->parent
;
164 bridge
= fake_bridge
->driver_priv
;
173 granularity
= 0x1000;
176 granularity
= 0x10000;
179 granularity
= 0x10000;
187 pr_err("Invalid address space\n");
192 * Bound address is a valid address for the window, adjust
195 vme_bound
= vme_base
+ size
- granularity
;
197 if (vme_base
& (granularity
- 1)) {
198 pr_err("Invalid VME base alignment\n");
201 if (vme_bound
& (granularity
- 1)) {
202 pr_err("Invalid VME bound alignment\n");
206 mutex_lock(&image
->mtx
);
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
;
215 mutex_unlock(&image
->mtx
);
221 * Get slave window configuration.
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
)
228 struct fake_driver
*bridge
;
230 bridge
= image
->parent
->driver_priv
;
234 mutex_lock(&image
->mtx
);
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
;
243 mutex_unlock(&image
->mtx
);
249 * Set the attributes of an outbound window.
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
)
257 struct vme_bridge
*fake_bridge
;
258 struct fake_driver
*bridge
;
260 fake_bridge
= image
->parent
;
262 bridge
= fake_bridge
->driver_priv
;
264 /* Verify input data */
265 if (vme_base
& 0xFFFF) {
266 pr_err("Invalid VME Window alignment\n");
272 pr_err("Invalid size alignment\n");
277 if ((size
== 0) && (enabled
!= 0)) {
278 pr_err("Size must be non-zero for enabled windows\n");
283 /* Setup data width */
290 pr_err("Invalid data width\n");
295 /* Setup address space */
308 pr_err("Invalid address space\n");
313 spin_lock(&image
->lock
);
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
;
324 spin_unlock(&image
->lock
);
336 * Set the attributes of an outbound window.
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
)
343 struct fake_driver
*bridge
;
345 bridge
= image
->parent
->driver_priv
;
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
;
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
)
366 spin_lock(&image
->lock
);
368 retval
= __fake_master_get(image
, enabled
, vme_base
, size
, aspace
,
371 spin_unlock(&image
->lock
);
377 static void fake_lm_check(struct fake_driver
*bridge
, unsigned long long addr
,
378 u32 aspace
, u32 cycle
)
380 struct vme_bridge
*fake_bridge
;
381 unsigned long long lm_base
;
382 u32 lm_aspace
, lm_cycle
;
384 struct vme_lm_resource
*lm
;
385 struct list_head
*pos
= NULL
, *n
;
388 fake_bridge
= bridge
->parent
;
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
);
394 /* If disabled, we're done */
395 if (bridge
->lm_enabled
== 0)
398 lm_base
= bridge
->lm_base
;
399 lm_aspace
= bridge
->lm_aspace
;
400 lm_cycle
= bridge
->lm_cycle
;
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
](
417 static u8
fake_vmeread8(struct fake_driver
*bridge
, unsigned long long addr
,
418 u32 aspace
, u32 cycle
)
422 unsigned long long start
, end
, offset
;
425 for (i
= 0; i
< FAKE_MAX_SLAVE
; i
++) {
426 start
= bridge
->slaves
[i
].vme_base
;
427 end
= bridge
->slaves
[i
].vme_base
+ bridge
->slaves
[i
].size
;
429 if (aspace
!= bridge
->slaves
[i
].aspace
)
432 if (cycle
!= bridge
->slaves
[i
].cycle
)
435 if ((addr
>= start
) && (addr
< end
)) {
436 offset
= addr
- bridge
->slaves
[i
].vme_base
;
437 loc
= (u8
*)(bridge
->slaves
[i
].buf_base
+ offset
);
444 fake_lm_check(bridge
, addr
, aspace
, cycle
);
449 static u16
fake_vmeread16(struct fake_driver
*bridge
, unsigned long long addr
,
450 u32 aspace
, u32 cycle
)
454 unsigned long long start
, end
, offset
;
457 for (i
= 0; i
< FAKE_MAX_SLAVE
; i
++) {
458 if (aspace
!= bridge
->slaves
[i
].aspace
)
461 if (cycle
!= bridge
->slaves
[i
].cycle
)
464 start
= bridge
->slaves
[i
].vme_base
;
465 end
= bridge
->slaves
[i
].vme_base
+ bridge
->slaves
[i
].size
;
467 if ((addr
>= start
) && ((addr
+ 1) < end
)) {
468 offset
= addr
- bridge
->slaves
[i
].vme_base
;
469 loc
= (u16
*)(bridge
->slaves
[i
].buf_base
+ offset
);
476 fake_lm_check(bridge
, addr
, aspace
, cycle
);
481 static u32
fake_vmeread32(struct fake_driver
*bridge
, unsigned long long addr
,
482 u32 aspace
, u32 cycle
)
484 u32 retval
= 0xffffffff;
486 unsigned long long start
, end
, offset
;
489 for (i
= 0; i
< FAKE_MAX_SLAVE
; i
++) {
490 if (aspace
!= bridge
->slaves
[i
].aspace
)
493 if (cycle
!= bridge
->slaves
[i
].cycle
)
496 start
= bridge
->slaves
[i
].vme_base
;
497 end
= bridge
->slaves
[i
].vme_base
+ bridge
->slaves
[i
].size
;
499 if ((addr
>= start
) && ((addr
+ 3) < end
)) {
500 offset
= addr
- bridge
->slaves
[i
].vme_base
;
501 loc
= (u32
*)(bridge
->slaves
[i
].buf_base
+ offset
);
508 fake_lm_check(bridge
, addr
, aspace
, cycle
);
513 static ssize_t
fake_master_read(struct vme_master_resource
*image
, void *buf
,
514 size_t count
, loff_t offset
)
517 u32 aspace
, cycle
, dwidth
;
518 struct vme_bridge
*fake_bridge
;
519 struct fake_driver
*priv
;
521 unsigned long long addr
;
522 unsigned int done
= 0;
523 unsigned int count32
;
525 fake_bridge
= image
->parent
;
527 priv
= fake_bridge
->driver_priv
;
531 addr
= (unsigned long long)priv
->masters
[i
].vme_base
+ offset
;
532 aspace
= priv
->masters
[i
].aspace
;
533 cycle
= priv
->masters
[i
].cycle
;
534 dwidth
= priv
->masters
[i
].dwidth
;
536 spin_lock(&image
->lock
);
538 /* The following code handles VME address alignment. We cannot use
539 * memcpy_xxx here because it may cut data transfers in to 8-bit
540 * cycles when D16 or D32 cycles are required on the VME bus.
541 * On the other hand, the bridge itself assures that the maximum data
542 * cycle configured for the transfer is used and splits it
543 * automatically for non-aligned addresses, so we don't want the
544 * overhead of needlessly forcing small transfers for the entire cycle.
547 *(u8
*)buf
= fake_vmeread8(priv
, addr
, aspace
, cycle
);
552 if ((dwidth
== VME_D16
) || (dwidth
== VME_D32
)) {
553 if ((addr
+ done
) & 0x2) {
554 if ((count
- done
) < 2) {
555 *(u8
*)(buf
+ done
) = fake_vmeread8(priv
,
556 addr
+ done
, aspace
, cycle
);
560 *(u16
*)(buf
+ done
) = fake_vmeread16(priv
,
561 addr
+ done
, aspace
, cycle
);
567 if (dwidth
== VME_D32
) {
568 count32
= (count
- done
) & ~0x3;
569 while (done
< count32
) {
570 *(u32
*)(buf
+ done
) = fake_vmeread32(priv
, addr
+ done
,
574 } else if (dwidth
== VME_D16
) {
575 count32
= (count
- done
) & ~0x3;
576 while (done
< count32
) {
577 *(u16
*)(buf
+ done
) = fake_vmeread16(priv
, addr
+ done
,
581 } else if (dwidth
== VME_D8
) {
582 count32
= (count
- done
);
583 while (done
< count32
) {
584 *(u8
*)(buf
+ done
) = fake_vmeread8(priv
, addr
+ done
,
591 if ((dwidth
== VME_D16
) || (dwidth
== VME_D32
)) {
592 if ((count
- done
) & 0x2) {
593 *(u16
*)(buf
+ done
) = fake_vmeread16(priv
, addr
+ done
,
598 if ((count
- done
) & 0x1) {
599 *(u8
*)(buf
+ done
) = fake_vmeread8(priv
, addr
+ done
, aspace
,
607 spin_unlock(&image
->lock
);
612 static void fake_vmewrite8(struct fake_driver
*bridge
, u8
*buf
,
613 unsigned long long addr
, u32 aspace
, u32 cycle
)
616 unsigned long long start
, end
, offset
;
619 for (i
= 0; i
< FAKE_MAX_SLAVE
; i
++) {
620 if (aspace
!= bridge
->slaves
[i
].aspace
)
623 if (cycle
!= bridge
->slaves
[i
].cycle
)
626 start
= bridge
->slaves
[i
].vme_base
;
627 end
= bridge
->slaves
[i
].vme_base
+ bridge
->slaves
[i
].size
;
629 if ((addr
>= start
) && (addr
< end
)) {
630 offset
= addr
- bridge
->slaves
[i
].vme_base
;
631 loc
= (u8
*)((void *)bridge
->slaves
[i
].buf_base
+ offset
);
638 fake_lm_check(bridge
, addr
, aspace
, cycle
);
642 static void fake_vmewrite16(struct fake_driver
*bridge
, u16
*buf
,
643 unsigned long long addr
, u32 aspace
, u32 cycle
)
646 unsigned long long start
, end
, offset
;
649 for (i
= 0; i
< FAKE_MAX_SLAVE
; i
++) {
650 if (aspace
!= bridge
->slaves
[i
].aspace
)
653 if (cycle
!= bridge
->slaves
[i
].cycle
)
656 start
= bridge
->slaves
[i
].vme_base
;
657 end
= bridge
->slaves
[i
].vme_base
+ bridge
->slaves
[i
].size
;
659 if ((addr
>= start
) && ((addr
+ 1) < end
)) {
660 offset
= addr
- bridge
->slaves
[i
].vme_base
;
661 loc
= (u16
*)((void *)bridge
->slaves
[i
].buf_base
+ offset
);
668 fake_lm_check(bridge
, addr
, aspace
, cycle
);
672 static void fake_vmewrite32(struct fake_driver
*bridge
, u32
*buf
,
673 unsigned long long addr
, u32 aspace
, u32 cycle
)
676 unsigned long long start
, end
, offset
;
679 for (i
= 0; i
< FAKE_MAX_SLAVE
; i
++) {
680 if (aspace
!= bridge
->slaves
[i
].aspace
)
683 if (cycle
!= bridge
->slaves
[i
].cycle
)
686 start
= bridge
->slaves
[i
].vme_base
;
687 end
= bridge
->slaves
[i
].vme_base
+ bridge
->slaves
[i
].size
;
689 if ((addr
>= start
) && ((addr
+ 3) < end
)) {
690 offset
= addr
- bridge
->slaves
[i
].vme_base
;
691 loc
= (u32
*)((void *)bridge
->slaves
[i
].buf_base
+ offset
);
698 fake_lm_check(bridge
, addr
, aspace
, cycle
);
702 static ssize_t
fake_master_write(struct vme_master_resource
*image
, void *buf
,
703 size_t count
, loff_t offset
)
706 u32 aspace
, cycle
, dwidth
;
707 unsigned long long addr
;
709 unsigned int done
= 0;
710 unsigned int count32
;
712 struct vme_bridge
*fake_bridge
;
713 struct fake_driver
*bridge
;
715 fake_bridge
= image
->parent
;
717 bridge
= fake_bridge
->driver_priv
;
721 addr
= bridge
->masters
[i
].vme_base
+ offset
;
722 aspace
= bridge
->masters
[i
].aspace
;
723 cycle
= bridge
->masters
[i
].cycle
;
724 dwidth
= bridge
->masters
[i
].dwidth
;
726 spin_lock(&image
->lock
);
728 /* Here we apply for the same strategy we do in master_read
729 * function in order to assure the correct cycles.
732 fake_vmewrite8(bridge
, (u8
*)buf
, addr
, aspace
, cycle
);
738 if ((dwidth
== VME_D16
) || (dwidth
== VME_D32
)) {
739 if ((addr
+ done
) & 0x2) {
740 if ((count
- done
) < 2) {
741 fake_vmewrite8(bridge
, (u8
*)(buf
+ done
),
742 addr
+ done
, aspace
, cycle
);
746 fake_vmewrite16(bridge
, (u16
*)(buf
+ done
),
747 addr
+ done
, aspace
, cycle
);
753 if (dwidth
== VME_D32
) {
754 count32
= (count
- done
) & ~0x3;
755 while (done
< count32
) {
756 fake_vmewrite32(bridge
, (u32
*)(buf
+ done
),
757 addr
+ done
, aspace
, cycle
);
760 } else if (dwidth
== VME_D16
) {
761 count32
= (count
- done
) & ~0x3;
762 while (done
< count32
) {
763 fake_vmewrite16(bridge
, (u16
*)(buf
+ done
),
764 addr
+ done
, aspace
, cycle
);
767 } else if (dwidth
== VME_D8
) {
768 count32
= (count
- done
);
769 while (done
< count32
) {
770 fake_vmewrite8(bridge
, (u8
*)(buf
+ done
), addr
+ done
,
777 if ((dwidth
== VME_D16
) || (dwidth
== VME_D32
)) {
778 if ((count
- done
) & 0x2) {
779 fake_vmewrite16(bridge
, (u16
*)(buf
+ done
),
780 addr
+ done
, aspace
, cycle
);
785 if ((count
- done
) & 0x1) {
786 fake_vmewrite8(bridge
, (u8
*)(buf
+ done
), addr
+ done
, aspace
,
794 spin_unlock(&image
->lock
);
800 * Perform an RMW cycle on the VME bus.
802 * Requires a previously configured master window, returns final value.
804 static unsigned int fake_master_rmw(struct vme_master_resource
*image
,
805 unsigned int mask
, unsigned int compare
, unsigned int swap
,
811 struct fake_driver
*bridge
;
813 bridge
= image
->parent
->driver_priv
;
815 /* Find the PCI address that maps to the desired VME address */
818 base
= bridge
->masters
[i
].vme_base
;
819 aspace
= bridge
->masters
[i
].aspace
;
820 cycle
= bridge
->masters
[i
].cycle
;
823 spin_lock(&image
->lock
);
825 /* Read existing value */
826 tmp
= fake_vmeread32(bridge
, base
+ offset
, aspace
, cycle
);
829 if ((tmp
&& mask
) == (compare
&& mask
)) {
830 tmp
= tmp
| (mask
| swap
);
831 tmp
= tmp
& (~mask
| swap
);
834 fake_vmewrite32(bridge
, &tmp
, base
+ offset
, aspace
, cycle
);
838 spin_unlock(&image
->lock
);
844 * All 4 location monitors reside at the same base - this is therefore a
845 * system wide configuration.
847 * This does not enable the LM monitor - that should be done when the first
848 * callback is attached and disabled when the last callback is removed.
850 static int fake_lm_set(struct vme_lm_resource
*lm
, unsigned long long lm_base
,
851 u32 aspace
, u32 cycle
)
854 struct vme_bridge
*fake_bridge
;
855 struct fake_driver
*bridge
;
857 fake_bridge
= lm
->parent
;
859 bridge
= fake_bridge
->driver_priv
;
861 mutex_lock(&lm
->mtx
);
863 /* If we already have a callback attached, we can't move it! */
864 for (i
= 0; i
< lm
->monitors
; i
++) {
865 if (bridge
->lm_callback
[i
]) {
866 mutex_unlock(&lm
->mtx
);
867 pr_err("Location monitor callback attached, can't reset\n");
879 mutex_unlock(&lm
->mtx
);
880 pr_err("Invalid address space\n");
884 bridge
->lm_base
= lm_base
;
885 bridge
->lm_aspace
= aspace
;
886 bridge
->lm_cycle
= cycle
;
888 mutex_unlock(&lm
->mtx
);
893 /* Get configuration of the callback monitor and return whether it is enabled
896 static int fake_lm_get(struct vme_lm_resource
*lm
,
897 unsigned long long *lm_base
, u32
*aspace
, u32
*cycle
)
899 struct fake_driver
*bridge
;
901 bridge
= lm
->parent
->driver_priv
;
903 mutex_lock(&lm
->mtx
);
905 *lm_base
= bridge
->lm_base
;
906 *aspace
= bridge
->lm_aspace
;
907 *cycle
= bridge
->lm_cycle
;
909 mutex_unlock(&lm
->mtx
);
911 return bridge
->lm_enabled
;
915 * Attach a callback to a specific location monitor.
917 * Callback will be passed the monitor triggered.
919 static int fake_lm_attach(struct vme_lm_resource
*lm
, int monitor
,
920 void (*callback
)(void *), void *data
)
922 struct vme_bridge
*fake_bridge
;
923 struct fake_driver
*bridge
;
925 fake_bridge
= lm
->parent
;
927 bridge
= fake_bridge
->driver_priv
;
929 mutex_lock(&lm
->mtx
);
931 /* Ensure that the location monitor is configured - need PGM or DATA */
932 if (bridge
->lm_cycle
== 0) {
933 mutex_unlock(&lm
->mtx
);
934 pr_err("Location monitor not properly configured\n");
938 /* Check that a callback isn't already attached */
939 if (bridge
->lm_callback
[monitor
]) {
940 mutex_unlock(&lm
->mtx
);
941 pr_err("Existing callback attached\n");
945 /* Attach callback */
946 bridge
->lm_callback
[monitor
] = callback
;
947 bridge
->lm_data
[monitor
] = data
;
949 /* Ensure that global Location Monitor Enable set */
950 bridge
->lm_enabled
= 1;
952 mutex_unlock(&lm
->mtx
);
958 * Detach a callback function forn a specific location monitor.
960 static int fake_lm_detach(struct vme_lm_resource
*lm
, int monitor
)
964 struct fake_driver
*bridge
;
966 bridge
= lm
->parent
->driver_priv
;
968 mutex_lock(&lm
->mtx
);
970 /* Detach callback */
971 bridge
->lm_callback
[monitor
] = NULL
;
972 bridge
->lm_data
[monitor
] = NULL
;
974 /* If all location monitors disabled, disable global Location Monitor */
976 for (i
= 0; i
< lm
->monitors
; i
++) {
977 if (bridge
->lm_callback
[i
])
982 bridge
->lm_enabled
= 0;
984 mutex_unlock(&lm
->mtx
);
990 * Determine Geographical Addressing
992 static int fake_slot_get(struct vme_bridge
*fake_bridge
)
997 static void *fake_alloc_consistent(struct device
*parent
, size_t size
,
1000 void *alloc
= kmalloc(size
, GFP_KERNEL
);
1003 *dma
= fake_ptr_to_pci(alloc
);
1008 static void fake_free_consistent(struct device
*parent
, size_t size
,
1009 void *vaddr
, dma_addr_t dma
)
1013 dma_free_coherent(parent, size, vaddr, dma);
1018 * Configure CR/CSR space
1020 * Access to the CR/CSR can be configured at power-up. The location of the
1021 * CR/CSR registers in the CR/CSR address space is determined by the boards
1022 * Geographic address.
1024 * Each board has a 512kB window, with the highest 4kB being used for the
1025 * boards registers, this means there is a fix length 508kB window which must
1026 * be mapped onto PCI memory.
1028 static int fake_crcsr_init(struct vme_bridge
*fake_bridge
)
1031 struct fake_driver
*bridge
;
1033 bridge
= fake_bridge
->driver_priv
;
1035 /* Allocate mem for CR/CSR image */
1036 bridge
->crcsr_kernel
= kzalloc(VME_CRCSR_BUF_SIZE
, GFP_KERNEL
);
1037 bridge
->crcsr_bus
= fake_ptr_to_pci(bridge
->crcsr_kernel
);
1038 if (!bridge
->crcsr_kernel
)
1041 vstat
= fake_slot_get(fake_bridge
);
1043 pr_info("CR/CSR Offset: %d\n", vstat
);
1048 static void fake_crcsr_exit(struct vme_bridge
*fake_bridge
)
1050 struct fake_driver
*bridge
;
1052 bridge
= fake_bridge
->driver_priv
;
1054 kfree(bridge
->crcsr_kernel
);
1058 static int __init
fake_init(void)
1061 struct list_head
*pos
= NULL
, *n
;
1062 struct vme_bridge
*fake_bridge
;
1063 struct fake_driver
*fake_device
;
1064 struct vme_master_resource
*master_image
;
1065 struct vme_slave_resource
*slave_image
;
1066 struct vme_lm_resource
*lm
;
1068 /* We need a fake parent device */
1069 vme_root
= __root_device_register("vme", THIS_MODULE
);
1071 /* If we want to support more than one bridge at some point, we need to
1072 * dynamically allocate this so we get one per device.
1074 fake_bridge
= kzalloc(sizeof(*fake_bridge
), GFP_KERNEL
);
1080 fake_device
= kzalloc(sizeof(*fake_device
), GFP_KERNEL
);
1086 fake_bridge
->driver_priv
= fake_device
;
1088 fake_bridge
->parent
= vme_root
;
1090 fake_device
->parent
= fake_bridge
;
1092 /* Initialize wait queues & mutual exclusion flags */
1093 mutex_init(&fake_device
->vme_int
);
1094 mutex_init(&fake_bridge
->irq_mtx
);
1095 tasklet_init(&fake_device
->int_tasklet
, fake_VIRQ_tasklet
,
1096 (unsigned long) fake_bridge
);
1098 strcpy(fake_bridge
->name
, driver_name
);
1100 /* Add master windows to list */
1101 INIT_LIST_HEAD(&fake_bridge
->master_resources
);
1102 for (i
= 0; i
< FAKE_MAX_MASTER
; i
++) {
1103 master_image
= kmalloc(sizeof(*master_image
), GFP_KERNEL
);
1104 if (!master_image
) {
1108 master_image
->parent
= fake_bridge
;
1109 spin_lock_init(&master_image
->lock
);
1110 master_image
->locked
= 0;
1111 master_image
->number
= i
;
1112 master_image
->address_attr
= VME_A16
| VME_A24
| VME_A32
|
1114 master_image
->cycle_attr
= VME_SCT
| VME_BLT
| VME_MBLT
|
1115 VME_2eVME
| VME_2eSST
| VME_2eSSTB
| VME_2eSST160
|
1116 VME_2eSST267
| VME_2eSST320
| VME_SUPER
| VME_USER
|
1117 VME_PROG
| VME_DATA
;
1118 master_image
->width_attr
= VME_D16
| VME_D32
;
1119 memset(&master_image
->bus_resource
, 0,
1120 sizeof(struct resource
));
1121 master_image
->kern_base
= NULL
;
1122 list_add_tail(&master_image
->list
,
1123 &fake_bridge
->master_resources
);
1126 /* Add slave windows to list */
1127 INIT_LIST_HEAD(&fake_bridge
->slave_resources
);
1128 for (i
= 0; i
< FAKE_MAX_SLAVE
; i
++) {
1129 slave_image
= kmalloc(sizeof(*slave_image
), GFP_KERNEL
);
1134 slave_image
->parent
= fake_bridge
;
1135 mutex_init(&slave_image
->mtx
);
1136 slave_image
->locked
= 0;
1137 slave_image
->number
= i
;
1138 slave_image
->address_attr
= VME_A16
| VME_A24
| VME_A32
|
1139 VME_A64
| VME_CRCSR
| VME_USER1
| VME_USER2
|
1140 VME_USER3
| VME_USER4
;
1141 slave_image
->cycle_attr
= VME_SCT
| VME_BLT
| VME_MBLT
|
1142 VME_2eVME
| VME_2eSST
| VME_2eSSTB
| VME_2eSST160
|
1143 VME_2eSST267
| VME_2eSST320
| VME_SUPER
| VME_USER
|
1144 VME_PROG
| VME_DATA
;
1145 list_add_tail(&slave_image
->list
,
1146 &fake_bridge
->slave_resources
);
1149 /* Add location monitor to list */
1150 INIT_LIST_HEAD(&fake_bridge
->lm_resources
);
1151 lm
= kmalloc(sizeof(*lm
), GFP_KERNEL
);
1156 lm
->parent
= fake_bridge
;
1157 mutex_init(&lm
->mtx
);
1161 list_add_tail(&lm
->list
, &fake_bridge
->lm_resources
);
1163 fake_bridge
->slave_get
= fake_slave_get
;
1164 fake_bridge
->slave_set
= fake_slave_set
;
1165 fake_bridge
->master_get
= fake_master_get
;
1166 fake_bridge
->master_set
= fake_master_set
;
1167 fake_bridge
->master_read
= fake_master_read
;
1168 fake_bridge
->master_write
= fake_master_write
;
1169 fake_bridge
->master_rmw
= fake_master_rmw
;
1170 fake_bridge
->irq_set
= fake_irq_set
;
1171 fake_bridge
->irq_generate
= fake_irq_generate
;
1172 fake_bridge
->lm_set
= fake_lm_set
;
1173 fake_bridge
->lm_get
= fake_lm_get
;
1174 fake_bridge
->lm_attach
= fake_lm_attach
;
1175 fake_bridge
->lm_detach
= fake_lm_detach
;
1176 fake_bridge
->slot_get
= fake_slot_get
;
1177 fake_bridge
->alloc_consistent
= fake_alloc_consistent
;
1178 fake_bridge
->free_consistent
= fake_free_consistent
;
1180 pr_info("Board is%s the VME system controller\n",
1181 (geoid
== 1) ? "" : " not");
1183 pr_info("VME geographical address is set to %d\n", geoid
);
1185 retval
= fake_crcsr_init(fake_bridge
);
1187 pr_err("CR/CSR configuration failed.\n");
1191 retval
= vme_register_bridge(fake_bridge
);
1193 pr_err("Chip Registration failed.\n");
1197 exit_pointer
= fake_bridge
;
1202 fake_crcsr_exit(fake_bridge
);
1205 /* resources are stored in link list */
1206 list_for_each_safe(pos
, n
, &fake_bridge
->lm_resources
) {
1207 lm
= list_entry(pos
, struct vme_lm_resource
, list
);
1212 /* resources are stored in link list */
1213 list_for_each_safe(pos
, n
, &fake_bridge
->slave_resources
) {
1214 slave_image
= list_entry(pos
, struct vme_slave_resource
, list
);
1219 /* resources are stored in link list */
1220 list_for_each_safe(pos
, n
, &fake_bridge
->master_resources
) {
1221 master_image
= list_entry(pos
, struct vme_master_resource
,
1224 kfree(master_image
);
1236 static void __exit
fake_exit(void)
1238 struct list_head
*pos
= NULL
;
1239 struct list_head
*tmplist
;
1240 struct vme_master_resource
*master_image
;
1241 struct vme_slave_resource
*slave_image
;
1243 struct vme_bridge
*fake_bridge
;
1244 struct fake_driver
*bridge
;
1246 fake_bridge
= exit_pointer
;
1248 bridge
= fake_bridge
->driver_priv
;
1250 pr_debug("Driver is being unloaded.\n");
1253 * Shutdown all inbound and outbound windows.
1255 for (i
= 0; i
< FAKE_MAX_MASTER
; i
++)
1256 bridge
->masters
[i
].enabled
= 0;
1258 for (i
= 0; i
< FAKE_MAX_SLAVE
; i
++)
1259 bridge
->slaves
[i
].enabled
= 0;
1262 * Shutdown Location monitor.
1264 bridge
->lm_enabled
= 0;
1266 vme_unregister_bridge(fake_bridge
);
1268 fake_crcsr_exit(fake_bridge
);
1269 /* resources are stored in link list */
1270 list_for_each_safe(pos
, tmplist
, &fake_bridge
->slave_resources
) {
1271 slave_image
= list_entry(pos
, struct vme_slave_resource
, list
);
1276 /* resources are stored in link list */
1277 list_for_each_safe(pos
, tmplist
, &fake_bridge
->master_resources
) {
1278 master_image
= list_entry(pos
, struct vme_master_resource
,
1281 kfree(master_image
);
1284 kfree(fake_bridge
->driver_priv
);
1288 root_device_unregister(vme_root
);
1292 MODULE_PARM_DESC(geoid
, "Set geographical addressing");
1293 module_param(geoid
, int, 0);
1295 MODULE_DESCRIPTION("Fake VME bridge driver");
1296 MODULE_LICENSE("GPL");
1298 module_init(fake_init
);
1299 module_exit(fake_exit
);