rcutorture: Eliminate unused ts_rem local from rcu_trace_clock_local()
[linux/fpc-iii.git] / drivers / vme / bridges / vme_fake.c
blob30b3acc9383309509862e0d1b942c22bc82a5361
1 /*
2 * Fake VME bridge support.
4 * This drive provides a fake VME bridge chip, this enables debugging of the
5 * VME framework in the absence of a VME system.
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.
11 * Author: Martyn Welch <martyn@welches.me.uk>
12 * Copyright (c) 2014 Martyn Welch
14 * Based on vme_tsi148.c:
16 * Author: Martyn Welch <martyn.welch@ge.com>
17 * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
19 * Based on work by Tom Armistead and Ajit Prem
20 * Copyright 2004 Motorola Inc.
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.
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>
38 #include "../vme_bridge.h"
41 * Define the number of each that the fake driver supports.
43 #define FAKE_MAX_MASTER 8 /* Max Master Windows */
44 #define FAKE_MAX_SLAVE 8 /* Max Slave Windows */
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;
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;
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;
85 /* Module parameter */
86 static int geoid;
88 static const char driver_name[] = "vme_fake";
90 static struct vme_bridge *exit_pointer;
92 static struct device *vme_root;
95 * Calling VME bus interrupt callback if provided.
97 static void fake_VIRQ_tasklet(unsigned long data)
99 struct vme_bridge *fake_bridge;
100 struct fake_driver *bridge;
102 fake_bridge = (struct vme_bridge *) data;
103 bridge = fake_bridge->driver_priv;
105 vme_irq_handler(fake_bridge, bridge->int_level, bridge->int_statid);
109 * Configure VME interrupt
111 static void fake_irq_set(struct vme_bridge *fake_bridge, int level,
112 int state, int sync)
114 /* Nothing to do */
117 static void *fake_pci_to_ptr(dma_addr_t addr)
119 return (void *)(uintptr_t)addr;
122 static dma_addr_t fake_ptr_to_pci(void *addr)
124 return (dma_addr_t)(uintptr_t)addr;
128 * Generate a VME bus interrupt at the requested level & vector. Wait for
129 * interrupt to be acked.
131 static int fake_irq_generate(struct vme_bridge *fake_bridge, int level,
132 int statid)
134 struct fake_driver *bridge;
136 bridge = fake_bridge->driver_priv;
138 mutex_lock(&bridge->vme_int);
140 bridge->int_level = level;
142 bridge->int_statid = statid;
145 * Schedule tasklet to run VME handler to emulate normal VME interrupt
146 * handler behaviour.
148 tasklet_schedule(&bridge->int_tasklet);
150 mutex_unlock(&bridge->vme_int);
152 return 0;
156 * Initialize a slave window with the requested attributes.
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)
162 unsigned int i, granularity = 0;
163 unsigned long long vme_bound;
164 struct vme_bridge *fake_bridge;
165 struct fake_driver *bridge;
167 fake_bridge = image->parent;
168 bridge = fake_bridge->driver_priv;
170 i = image->number;
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;
196 * Bound address is a valid address for the window, adjust
197 * accordingly
199 vme_bound = vme_base + size - granularity;
201 if (vme_base & (granularity - 1)) {
202 pr_err("Invalid VME base alignment\n");
203 return -EINVAL;
205 if (vme_bound & (granularity - 1)) {
206 pr_err("Invalid VME bound alignment\n");
207 return -EINVAL;
210 mutex_lock(&image->mtx);
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;
219 mutex_unlock(&image->mtx);
221 return 0;
225 * Get slave window configuration.
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)
231 unsigned int i;
232 struct fake_driver *bridge;
234 bridge = image->parent->driver_priv;
236 i = image->number;
238 mutex_lock(&image->mtx);
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;
247 mutex_unlock(&image->mtx);
249 return 0;
253 * Set the attributes of an outbound window.
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)
259 int retval = 0;
260 unsigned int i;
261 struct vme_bridge *fake_bridge;
262 struct fake_driver *bridge;
264 fake_bridge = image->parent;
266 bridge = fake_bridge->driver_priv;
268 /* Verify input data */
269 if (vme_base & 0xFFFF) {
270 pr_err("Invalid VME Window alignment\n");
271 retval = -EINVAL;
272 goto err_window;
275 if (size & 0xFFFF) {
276 pr_err("Invalid size alignment\n");
277 retval = -EINVAL;
278 goto err_window;
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;
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;
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;
317 spin_lock(&image->lock);
319 i = image->number;
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;
328 spin_unlock(&image->lock);
330 return 0;
332 err_aspace:
333 err_dwidth:
334 err_window:
335 return retval;
340 * Set the attributes of an outbound window.
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)
346 unsigned int i;
347 struct fake_driver *bridge;
349 bridge = image->parent->driver_priv;
351 i = image->number;
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;
360 return 0;
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)
368 int retval;
370 spin_lock(&image->lock);
372 retval = __fake_master_get(image, enabled, vme_base, size, aspace,
373 cycle, dwidth);
375 spin_unlock(&image->lock);
377 return retval;
381 static void fake_lm_check(struct fake_driver *bridge, unsigned long long addr,
382 u32 aspace, u32 cycle)
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;
391 /* Get vme_bridge */
392 fake_bridge = bridge->parent;
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);
398 /* If disabled, we're done */
399 if (bridge->lm_enabled == 0)
400 return;
402 lm_base = bridge->lm_base;
403 lm_aspace = bridge->lm_aspace;
404 lm_cycle = bridge->lm_cycle;
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]);
421 static u8 fake_vmeread8(struct fake_driver *bridge, unsigned long long addr,
422 u32 aspace, u32 cycle)
424 u8 retval = 0xff;
425 int i;
426 unsigned long long start, end, offset;
427 u8 *loc;
429 for (i = 0; i < FAKE_MAX_SLAVE; i++) {
430 start = bridge->slaves[i].vme_base;
431 end = bridge->slaves[i].vme_base + bridge->slaves[i].size;
433 if (aspace != bridge->slaves[i].aspace)
434 continue;
436 if (cycle != bridge->slaves[i].cycle)
437 continue;
439 if ((addr >= start) && (addr < end)) {
440 offset = addr - bridge->slaves[i].vme_base;
441 loc = (u8 *)(bridge->slaves[i].buf_base + offset);
442 retval = *loc;
444 break;
448 fake_lm_check(bridge, addr, aspace, cycle);
450 return retval;
453 static u16 fake_vmeread16(struct fake_driver *bridge, unsigned long long addr,
454 u32 aspace, u32 cycle)
456 u16 retval = 0xffff;
457 int i;
458 unsigned long long start, end, offset;
459 u16 *loc;
461 for (i = 0; i < FAKE_MAX_SLAVE; i++) {
462 if (aspace != bridge->slaves[i].aspace)
463 continue;
465 if (cycle != bridge->slaves[i].cycle)
466 continue;
468 start = bridge->slaves[i].vme_base;
469 end = bridge->slaves[i].vme_base + bridge->slaves[i].size;
471 if ((addr >= start) && ((addr + 1) < end)) {
472 offset = addr - bridge->slaves[i].vme_base;
473 loc = (u16 *)(bridge->slaves[i].buf_base + offset);
474 retval = *loc;
476 break;
480 fake_lm_check(bridge, addr, aspace, cycle);
482 return retval;
485 static u32 fake_vmeread32(struct fake_driver *bridge, unsigned long long addr,
486 u32 aspace, u32 cycle)
488 u32 retval = 0xffffffff;
489 int i;
490 unsigned long long start, end, offset;
491 u32 *loc;
493 for (i = 0; i < FAKE_MAX_SLAVE; i++) {
494 if (aspace != bridge->slaves[i].aspace)
495 continue;
497 if (cycle != bridge->slaves[i].cycle)
498 continue;
500 start = bridge->slaves[i].vme_base;
501 end = bridge->slaves[i].vme_base + bridge->slaves[i].size;
503 if ((addr >= start) && ((addr + 3) < end)) {
504 offset = addr - bridge->slaves[i].vme_base;
505 loc = (u32 *)(bridge->slaves[i].buf_base + offset);
506 retval = *loc;
508 break;
512 fake_lm_check(bridge, addr, aspace, cycle);
514 return retval;
517 static ssize_t fake_master_read(struct vme_master_resource *image, void *buf,
518 size_t count, loff_t offset)
520 int retval;
521 u32 aspace, cycle, dwidth;
522 struct vme_bridge *fake_bridge;
523 struct fake_driver *priv;
524 int i;
525 unsigned long long addr;
526 unsigned int done = 0;
527 unsigned int count32;
529 fake_bridge = image->parent;
531 priv = fake_bridge->driver_priv;
533 i = image->number;
535 addr = (unsigned long long)priv->masters[i].vme_base + offset;
536 aspace = priv->masters[i].aspace;
537 cycle = priv->masters[i].cycle;
538 dwidth = priv->masters[i].dwidth;
540 spin_lock(&image->lock);
542 /* The following code handles VME address alignment. We cannot use
543 * memcpy_xxx here because it may cut data transfers in to 8-bit
544 * cycles when D16 or D32 cycles are required on the VME bus.
545 * On the other hand, the bridge itself assures that the maximum data
546 * cycle configured for the transfer is used and splits it
547 * automatically for non-aligned addresses, so we don't want the
548 * overhead of needlessly forcing small transfers for the entire cycle.
550 if (addr & 0x1) {
551 *(u8 *)buf = fake_vmeread8(priv, addr, aspace, cycle);
552 done += 1;
553 if (done == count)
554 goto out;
556 if ((dwidth == VME_D16) || (dwidth == VME_D32)) {
557 if ((addr + done) & 0x2) {
558 if ((count - done) < 2) {
559 *(u8 *)(buf + done) = fake_vmeread8(priv,
560 addr + done, aspace, cycle);
561 done += 1;
562 goto out;
563 } else {
564 *(u16 *)(buf + done) = fake_vmeread16(priv,
565 addr + done, aspace, cycle);
566 done += 2;
571 if (dwidth == VME_D32) {
572 count32 = (count - done) & ~0x3;
573 while (done < count32) {
574 *(u32 *)(buf + done) = fake_vmeread32(priv, addr + done,
575 aspace, cycle);
576 done += 4;
578 } else if (dwidth == VME_D16) {
579 count32 = (count - done) & ~0x3;
580 while (done < count32) {
581 *(u16 *)(buf + done) = fake_vmeread16(priv, addr + done,
582 aspace, cycle);
583 done += 2;
585 } else if (dwidth == VME_D8) {
586 count32 = (count - done);
587 while (done < count32) {
588 *(u8 *)(buf + done) = fake_vmeread8(priv, addr + done,
589 aspace, cycle);
590 done += 1;
595 if ((dwidth == VME_D16) || (dwidth == VME_D32)) {
596 if ((count - done) & 0x2) {
597 *(u16 *)(buf + done) = fake_vmeread16(priv, addr + done,
598 aspace, cycle);
599 done += 2;
602 if ((count - done) & 0x1) {
603 *(u8 *)(buf + done) = fake_vmeread8(priv, addr + done, aspace,
604 cycle);
605 done += 1;
608 out:
609 retval = count;
611 spin_unlock(&image->lock);
613 return retval;
616 static void fake_vmewrite8(struct fake_driver *bridge, u8 *buf,
617 unsigned long long addr, u32 aspace, u32 cycle)
619 int i;
620 unsigned long long start, end, offset;
621 u8 *loc;
623 for (i = 0; i < FAKE_MAX_SLAVE; i++) {
624 if (aspace != bridge->slaves[i].aspace)
625 continue;
627 if (cycle != bridge->slaves[i].cycle)
628 continue;
630 start = bridge->slaves[i].vme_base;
631 end = bridge->slaves[i].vme_base + bridge->slaves[i].size;
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;
638 break;
642 fake_lm_check(bridge, addr, aspace, cycle);
646 static void fake_vmewrite16(struct fake_driver *bridge, u16 *buf,
647 unsigned long long addr, u32 aspace, u32 cycle)
649 int i;
650 unsigned long long start, end, offset;
651 u16 *loc;
653 for (i = 0; i < FAKE_MAX_SLAVE; i++) {
654 if (aspace != bridge->slaves[i].aspace)
655 continue;
657 if (cycle != bridge->slaves[i].cycle)
658 continue;
660 start = bridge->slaves[i].vme_base;
661 end = bridge->slaves[i].vme_base + bridge->slaves[i].size;
663 if ((addr >= start) && ((addr + 1) < end)) {
664 offset = addr - bridge->slaves[i].vme_base;
665 loc = (u16 *)((void *)bridge->slaves[i].buf_base + offset);
666 *loc = *buf;
668 break;
672 fake_lm_check(bridge, addr, aspace, cycle);
676 static void fake_vmewrite32(struct fake_driver *bridge, u32 *buf,
677 unsigned long long addr, u32 aspace, u32 cycle)
679 int i;
680 unsigned long long start, end, offset;
681 u32 *loc;
683 for (i = 0; i < FAKE_MAX_SLAVE; i++) {
684 if (aspace != bridge->slaves[i].aspace)
685 continue;
687 if (cycle != bridge->slaves[i].cycle)
688 continue;
690 start = bridge->slaves[i].vme_base;
691 end = bridge->slaves[i].vme_base + bridge->slaves[i].size;
693 if ((addr >= start) && ((addr + 3) < end)) {
694 offset = addr - bridge->slaves[i].vme_base;
695 loc = (u32 *)((void *)bridge->slaves[i].buf_base + offset);
696 *loc = *buf;
698 break;
702 fake_lm_check(bridge, addr, aspace, cycle);
706 static ssize_t fake_master_write(struct vme_master_resource *image, void *buf,
707 size_t count, loff_t offset)
709 int retval = 0;
710 u32 aspace, cycle, dwidth;
711 unsigned long long addr;
712 int i;
713 unsigned int done = 0;
714 unsigned int count32;
716 struct vme_bridge *fake_bridge;
717 struct fake_driver *bridge;
719 fake_bridge = image->parent;
721 bridge = fake_bridge->driver_priv;
723 i = image->number;
725 addr = bridge->masters[i].vme_base + offset;
726 aspace = bridge->masters[i].aspace;
727 cycle = bridge->masters[i].cycle;
728 dwidth = bridge->masters[i].dwidth;
730 spin_lock(&image->lock);
732 /* Here we apply for the same strategy we do in master_read
733 * function in order to assure the correct cycles.
735 if (addr & 0x1) {
736 fake_vmewrite8(bridge, (u8 *)buf, addr, aspace, cycle);
737 done += 1;
738 if (done == count)
739 goto out;
742 if ((dwidth == VME_D16) || (dwidth == VME_D32)) {
743 if ((addr + done) & 0x2) {
744 if ((count - done) < 2) {
745 fake_vmewrite8(bridge, (u8 *)(buf + done),
746 addr + done, aspace, cycle);
747 done += 1;
748 goto out;
749 } else {
750 fake_vmewrite16(bridge, (u16 *)(buf + done),
751 addr + done, aspace, cycle);
752 done += 2;
757 if (dwidth == VME_D32) {
758 count32 = (count - done) & ~0x3;
759 while (done < count32) {
760 fake_vmewrite32(bridge, (u32 *)(buf + done),
761 addr + done, aspace, cycle);
762 done += 4;
764 } else if (dwidth == VME_D16) {
765 count32 = (count - done) & ~0x3;
766 while (done < count32) {
767 fake_vmewrite16(bridge, (u16 *)(buf + done),
768 addr + done, aspace, cycle);
769 done += 2;
771 } else if (dwidth == VME_D8) {
772 count32 = (count - done);
773 while (done < count32) {
774 fake_vmewrite8(bridge, (u8 *)(buf + done), addr + done,
775 aspace, cycle);
776 done += 1;
781 if ((dwidth == VME_D16) || (dwidth == VME_D32)) {
782 if ((count - done) & 0x2) {
783 fake_vmewrite16(bridge, (u16 *)(buf + done),
784 addr + done, aspace, cycle);
785 done += 2;
789 if ((count - done) & 0x1) {
790 fake_vmewrite8(bridge, (u8 *)(buf + done), addr + done, aspace,
791 cycle);
792 done += 1;
795 out:
796 retval = count;
798 spin_unlock(&image->lock);
800 return retval;
804 * Perform an RMW cycle on the VME bus.
806 * Requires a previously configured master window, returns final value.
808 static unsigned int fake_master_rmw(struct vme_master_resource *image,
809 unsigned int mask, unsigned int compare, unsigned int swap,
810 loff_t offset)
812 u32 tmp, base;
813 u32 aspace, cycle;
814 int i;
815 struct fake_driver *bridge;
817 bridge = image->parent->driver_priv;
819 /* Find the PCI address that maps to the desired VME address */
820 i = image->number;
822 base = bridge->masters[i].vme_base;
823 aspace = bridge->masters[i].aspace;
824 cycle = bridge->masters[i].cycle;
826 /* Lock image */
827 spin_lock(&image->lock);
829 /* Read existing value */
830 tmp = fake_vmeread32(bridge, base + offset, aspace, cycle);
832 /* Perform check */
833 if ((tmp && mask) == (compare && mask)) {
834 tmp = tmp | (mask | swap);
835 tmp = tmp & (~mask | swap);
837 /* Write back */
838 fake_vmewrite32(bridge, &tmp, base + offset, aspace, cycle);
841 /* Unlock image */
842 spin_unlock(&image->lock);
844 return tmp;
848 * All 4 location monitors reside at the same base - this is therefore a
849 * system wide configuration.
851 * This does not enable the LM monitor - that should be done when the first
852 * callback is attached and disabled when the last callback is removed.
854 static int fake_lm_set(struct vme_lm_resource *lm, unsigned long long lm_base,
855 u32 aspace, u32 cycle)
857 int i;
858 struct vme_bridge *fake_bridge;
859 struct fake_driver *bridge;
861 fake_bridge = lm->parent;
863 bridge = fake_bridge->driver_priv;
865 mutex_lock(&lm->mtx);
867 /* If we already have a callback attached, we can't move it! */
868 for (i = 0; i < lm->monitors; i++) {
869 if (bridge->lm_callback[i] != NULL) {
870 mutex_unlock(&lm->mtx);
871 pr_err("Location monitor callback attached, can't reset\n");
872 return -EBUSY;
876 switch (aspace) {
877 case VME_A16:
878 case VME_A24:
879 case VME_A32:
880 case VME_A64:
881 break;
882 default:
883 mutex_unlock(&lm->mtx);
884 pr_err("Invalid address space\n");
885 return -EINVAL;
888 bridge->lm_base = lm_base;
889 bridge->lm_aspace = aspace;
890 bridge->lm_cycle = cycle;
892 mutex_unlock(&lm->mtx);
894 return 0;
897 /* Get configuration of the callback monitor and return whether it is enabled
898 * or disabled.
900 static int fake_lm_get(struct vme_lm_resource *lm,
901 unsigned long long *lm_base, u32 *aspace, u32 *cycle)
903 struct fake_driver *bridge;
905 bridge = lm->parent->driver_priv;
907 mutex_lock(&lm->mtx);
909 *lm_base = bridge->lm_base;
910 *aspace = bridge->lm_aspace;
911 *cycle = bridge->lm_cycle;
913 mutex_unlock(&lm->mtx);
915 return bridge->lm_enabled;
919 * Attach a callback to a specific location monitor.
921 * Callback will be passed the monitor triggered.
923 static int fake_lm_attach(struct vme_lm_resource *lm, int monitor,
924 void (*callback)(void *), void *data)
926 struct vme_bridge *fake_bridge;
927 struct fake_driver *bridge;
929 fake_bridge = lm->parent;
931 bridge = fake_bridge->driver_priv;
933 mutex_lock(&lm->mtx);
935 /* Ensure that the location monitor is configured - need PGM or DATA */
936 if (bridge->lm_cycle == 0) {
937 mutex_unlock(&lm->mtx);
938 pr_err("Location monitor not properly configured\n");
939 return -EINVAL;
942 /* Check that a callback isn't already attached */
943 if (bridge->lm_callback[monitor] != NULL) {
944 mutex_unlock(&lm->mtx);
945 pr_err("Existing callback attached\n");
946 return -EBUSY;
949 /* Attach callback */
950 bridge->lm_callback[monitor] = callback;
951 bridge->lm_data[monitor] = data;
953 /* Ensure that global Location Monitor Enable set */
954 bridge->lm_enabled = 1;
956 mutex_unlock(&lm->mtx);
958 return 0;
962 * Detach a callback function forn a specific location monitor.
964 static int fake_lm_detach(struct vme_lm_resource *lm, int monitor)
966 u32 tmp;
967 int i;
968 struct fake_driver *bridge;
970 bridge = lm->parent->driver_priv;
972 mutex_lock(&lm->mtx);
974 /* Detach callback */
975 bridge->lm_callback[monitor] = NULL;
976 bridge->lm_data[monitor] = NULL;
978 /* If all location monitors disabled, disable global Location Monitor */
979 tmp = 0;
980 for (i = 0; i < lm->monitors; i++) {
981 if (bridge->lm_callback[i] != NULL)
982 tmp = 1;
985 if (tmp == 0)
986 bridge->lm_enabled = 0;
988 mutex_unlock(&lm->mtx);
990 return 0;
994 * Determine Geographical Addressing
996 static int fake_slot_get(struct vme_bridge *fake_bridge)
998 return geoid;
1001 static void *fake_alloc_consistent(struct device *parent, size_t size,
1002 dma_addr_t *dma)
1004 void *alloc = kmalloc(size, GFP_KERNEL);
1006 if (alloc != NULL)
1007 *dma = fake_ptr_to_pci(alloc);
1009 return alloc;
1012 static void fake_free_consistent(struct device *parent, size_t size,
1013 void *vaddr, dma_addr_t dma)
1015 kfree(vaddr);
1017 dma_free_coherent(parent, size, vaddr, dma);
1022 * Configure CR/CSR space
1024 * Access to the CR/CSR can be configured at power-up. The location of the
1025 * CR/CSR registers in the CR/CSR address space is determined by the boards
1026 * Geographic address.
1028 * Each board has a 512kB window, with the highest 4kB being used for the
1029 * boards registers, this means there is a fix length 508kB window which must
1030 * be mapped onto PCI memory.
1032 static int fake_crcsr_init(struct vme_bridge *fake_bridge)
1034 u32 vstat;
1035 struct fake_driver *bridge;
1037 bridge = fake_bridge->driver_priv;
1039 /* Allocate mem for CR/CSR image */
1040 bridge->crcsr_kernel = kzalloc(VME_CRCSR_BUF_SIZE, GFP_KERNEL);
1041 bridge->crcsr_bus = fake_ptr_to_pci(bridge->crcsr_kernel);
1042 if (bridge->crcsr_kernel == NULL)
1043 return -ENOMEM;
1045 vstat = fake_slot_get(fake_bridge);
1047 pr_info("CR/CSR Offset: %d\n", vstat);
1049 return 0;
1052 static void fake_crcsr_exit(struct vme_bridge *fake_bridge)
1054 struct fake_driver *bridge;
1056 bridge = fake_bridge->driver_priv;
1058 kfree(bridge->crcsr_kernel);
1062 static int __init fake_init(void)
1064 int retval, i;
1065 struct list_head *pos = NULL, *n;
1066 struct vme_bridge *fake_bridge;
1067 struct fake_driver *fake_device;
1068 struct vme_master_resource *master_image;
1069 struct vme_slave_resource *slave_image;
1070 struct vme_lm_resource *lm;
1072 /* We need a fake parent device */
1073 vme_root = __root_device_register("vme", THIS_MODULE);
1075 /* If we want to support more than one bridge at some point, we need to
1076 * dynamically allocate this so we get one per device.
1078 fake_bridge = kzalloc(sizeof(struct vme_bridge), GFP_KERNEL);
1079 if (fake_bridge == NULL) {
1080 retval = -ENOMEM;
1081 goto err_struct;
1084 fake_device = kzalloc(sizeof(struct fake_driver), GFP_KERNEL);
1085 if (fake_device == NULL) {
1086 retval = -ENOMEM;
1087 goto err_driver;
1090 fake_bridge->driver_priv = fake_device;
1092 fake_bridge->parent = vme_root;
1094 fake_device->parent = fake_bridge;
1096 /* Initialize wait queues & mutual exclusion flags */
1097 mutex_init(&fake_device->vme_int);
1098 mutex_init(&fake_bridge->irq_mtx);
1099 tasklet_init(&fake_device->int_tasklet, fake_VIRQ_tasklet,
1100 (unsigned long) fake_bridge);
1102 strcpy(fake_bridge->name, driver_name);
1104 /* Add master windows to list */
1105 INIT_LIST_HEAD(&fake_bridge->master_resources);
1106 for (i = 0; i < FAKE_MAX_MASTER; i++) {
1107 master_image = kmalloc(sizeof(struct vme_master_resource),
1108 GFP_KERNEL);
1109 if (master_image == NULL) {
1110 retval = -ENOMEM;
1111 goto err_master;
1113 master_image->parent = fake_bridge;
1114 spin_lock_init(&master_image->lock);
1115 master_image->locked = 0;
1116 master_image->number = i;
1117 master_image->address_attr = VME_A16 | VME_A24 | VME_A32 |
1118 VME_A64;
1119 master_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT |
1120 VME_2eVME | VME_2eSST | VME_2eSSTB | VME_2eSST160 |
1121 VME_2eSST267 | VME_2eSST320 | VME_SUPER | VME_USER |
1122 VME_PROG | VME_DATA;
1123 master_image->width_attr = VME_D16 | VME_D32;
1124 memset(&master_image->bus_resource, 0,
1125 sizeof(struct resource));
1126 master_image->kern_base = NULL;
1127 list_add_tail(&master_image->list,
1128 &fake_bridge->master_resources);
1131 /* Add slave windows to list */
1132 INIT_LIST_HEAD(&fake_bridge->slave_resources);
1133 for (i = 0; i < FAKE_MAX_SLAVE; i++) {
1134 slave_image = kmalloc(sizeof(struct vme_slave_resource),
1135 GFP_KERNEL);
1136 if (slave_image == NULL) {
1137 retval = -ENOMEM;
1138 goto err_slave;
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);
1155 /* Add location monitor to list */
1156 INIT_LIST_HEAD(&fake_bridge->lm_resources);
1157 lm = kmalloc(sizeof(struct vme_lm_resource), GFP_KERNEL);
1158 if (lm == NULL) {
1159 pr_err("Failed to allocate memory for location monitor resource structure\n");
1160 retval = -ENOMEM;
1161 goto err_lm;
1163 lm->parent = fake_bridge;
1164 mutex_init(&lm->mtx);
1165 lm->locked = 0;
1166 lm->number = 1;
1167 lm->monitors = 4;
1168 list_add_tail(&lm->list, &fake_bridge->lm_resources);
1170 fake_bridge->slave_get = fake_slave_get;
1171 fake_bridge->slave_set = fake_slave_set;
1172 fake_bridge->master_get = fake_master_get;
1173 fake_bridge->master_set = fake_master_set;
1174 fake_bridge->master_read = fake_master_read;
1175 fake_bridge->master_write = fake_master_write;
1176 fake_bridge->master_rmw = fake_master_rmw;
1177 fake_bridge->irq_set = fake_irq_set;
1178 fake_bridge->irq_generate = fake_irq_generate;
1179 fake_bridge->lm_set = fake_lm_set;
1180 fake_bridge->lm_get = fake_lm_get;
1181 fake_bridge->lm_attach = fake_lm_attach;
1182 fake_bridge->lm_detach = fake_lm_detach;
1183 fake_bridge->slot_get = fake_slot_get;
1184 fake_bridge->alloc_consistent = fake_alloc_consistent;
1185 fake_bridge->free_consistent = fake_free_consistent;
1187 pr_info("Board is%s the VME system controller\n",
1188 (geoid == 1) ? "" : " not");
1190 pr_info("VME geographical address is set to %d\n", geoid);
1192 retval = fake_crcsr_init(fake_bridge);
1193 if (retval) {
1194 pr_err("CR/CSR configuration failed.\n");
1195 goto err_crcsr;
1198 retval = vme_register_bridge(fake_bridge);
1199 if (retval != 0) {
1200 pr_err("Chip Registration failed.\n");
1201 goto err_reg;
1204 exit_pointer = fake_bridge;
1206 return 0;
1208 err_reg:
1209 fake_crcsr_exit(fake_bridge);
1210 err_crcsr:
1211 err_lm:
1212 /* resources are stored in link list */
1213 list_for_each_safe(pos, n, &fake_bridge->lm_resources) {
1214 lm = list_entry(pos, struct vme_lm_resource, list);
1215 list_del(pos);
1216 kfree(lm);
1218 err_slave:
1219 /* resources are stored in link list */
1220 list_for_each_safe(pos, n, &fake_bridge->slave_resources) {
1221 slave_image = list_entry(pos, struct vme_slave_resource, list);
1222 list_del(pos);
1223 kfree(slave_image);
1225 err_master:
1226 /* resources are stored in link list */
1227 list_for_each_safe(pos, n, &fake_bridge->master_resources) {
1228 master_image = list_entry(pos, struct vme_master_resource,
1229 list);
1230 list_del(pos);
1231 kfree(master_image);
1234 kfree(fake_device);
1235 err_driver:
1236 kfree(fake_bridge);
1237 err_struct:
1238 return retval;
1243 static void __exit fake_exit(void)
1245 struct list_head *pos = NULL;
1246 struct list_head *tmplist;
1247 struct vme_master_resource *master_image;
1248 struct vme_slave_resource *slave_image;
1249 int i;
1250 struct vme_bridge *fake_bridge;
1251 struct fake_driver *bridge;
1253 fake_bridge = exit_pointer;
1255 bridge = fake_bridge->driver_priv;
1257 pr_debug("Driver is being unloaded.\n");
1260 * Shutdown all inbound and outbound windows.
1262 for (i = 0; i < FAKE_MAX_MASTER; i++)
1263 bridge->masters[i].enabled = 0;
1265 for (i = 0; i < FAKE_MAX_SLAVE; i++)
1266 bridge->slaves[i].enabled = 0;
1269 * Shutdown Location monitor.
1271 bridge->lm_enabled = 0;
1273 vme_unregister_bridge(fake_bridge);
1275 fake_crcsr_exit(fake_bridge);
1276 /* resources are stored in link list */
1277 list_for_each_safe(pos, tmplist, &fake_bridge->slave_resources) {
1278 slave_image = list_entry(pos, struct vme_slave_resource, list);
1279 list_del(pos);
1280 kfree(slave_image);
1283 /* resources are stored in link list */
1284 list_for_each_safe(pos, tmplist, &fake_bridge->master_resources) {
1285 master_image = list_entry(pos, struct vme_master_resource,
1286 list);
1287 list_del(pos);
1288 kfree(master_image);
1291 kfree(fake_bridge->driver_priv);
1293 kfree(fake_bridge);
1295 root_device_unregister(vme_root);
1299 MODULE_PARM_DESC(geoid, "Set geographical addressing");
1300 module_param(geoid, int, 0);
1302 MODULE_DESCRIPTION("Fake VME bridge driver");
1303 MODULE_LICENSE("GPL");
1305 module_init(fake_init);
1306 module_exit(fake_exit);