aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/sbus/sbus.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-06-20 18:23:28 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-06-24 02:15:00 -0400
commit8fae097debdf8ac9b66d220ac258535ea09f3898 (patch)
tree9c022cbf14e9174946a503b116fdf7376b8ce0ce /drivers/sbus/sbus.c
parentd384ea691fe4ea8c2dd5b9b8d9042eb181776f18 (diff)
[SBUS]: Start cleaning up generic sbus support layer.
In particular, move the IRQ probing out to sparc32/sparc64 arch specific code where it belongs. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/sbus/sbus.c')
-rw-r--r--drivers/sbus/sbus.c143
1 files changed, 19 insertions, 124 deletions
diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c
index 5d30a3ebfccd..6e9b2608202b 100644
--- a/drivers/sbus/sbus.c
+++ b/drivers/sbus/sbus.c
@@ -1,7 +1,6 @@
1/* $Id: sbus.c,v 1.100 2002/01/24 15:36:24 davem Exp $ 1/* sbus.c: SBus support routines.
2 * sbus.c: SBus support routines.
3 * 2 *
4 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) 3 * Copyright (C) 1995, 2006 David S. Miller (davem@davemloft.net)
5 */ 4 */
6 5
7#include <linux/kernel.h> 6#include <linux/kernel.h>
@@ -17,29 +16,12 @@
17#include <asm/bpp.h> 16#include <asm/bpp.h>
18#include <asm/irq.h> 17#include <asm/irq.h>
19 18
20struct sbus_bus *sbus_root = NULL; 19struct sbus_bus *sbus_root;
21
22static struct linux_prom_irqs irqs[PROMINTR_MAX] __initdata = { { 0 } };
23#ifdef CONFIG_SPARC32
24static int interrupts[PROMINTR_MAX] __initdata = { 0 };
25#endif
26 20
27#ifdef CONFIG_PCI 21#ifdef CONFIG_PCI
28extern int pcic_present(void); 22extern int pcic_present(void);
29#endif 23#endif
30 24
31/* Perhaps when I figure out more about the iommu we'll put a
32 * device registration routine here that probe_sbus() calls to
33 * setup the iommu for each Sbus.
34 */
35
36/* We call this for each SBus device, and fill the structure based
37 * upon the prom device tree. We return the start of memory after
38 * the things we have allocated.
39 */
40
41/* #define DEBUG_FILL */
42
43static void __init fill_sbus_device(int prom_node, struct sbus_dev *sdev) 25static void __init fill_sbus_device(int prom_node, struct sbus_dev *sdev)
44{ 26{
45 unsigned long address, base; 27 unsigned long address, base;
@@ -52,117 +34,30 @@ static void __init fill_sbus_device(int prom_node, struct sbus_dev *sdev)
52 len = prom_getproperty(prom_node, "reg", 34 len = prom_getproperty(prom_node, "reg",
53 (char *) sdev->reg_addrs, 35 (char *) sdev->reg_addrs,
54 sizeof(sdev->reg_addrs)); 36 sizeof(sdev->reg_addrs));
55 if (len == -1) { 37 sdev->num_registers = 0;
56 sdev->num_registers = 0; 38 if (len != -1) {
57 goto no_regs; 39 sdev->num_registers =
58 } 40 len / sizeof(struct linux_prom_registers);
59 41 sdev->ranges_applied = 0;
60 if (len % sizeof(struct linux_prom_registers)) {
61 prom_printf("fill_sbus_device: proplen for regs of %s "
62 " was %d, need multiple of %d\n",
63 sdev->prom_name, len,
64 (int) sizeof(struct linux_prom_registers));
65 prom_halt();
66 }
67 if (len > (sizeof(struct linux_prom_registers) * PROMREG_MAX)) {
68 prom_printf("fill_sbus_device: Too many register properties "
69 "for device %s, len=%d\n",
70 sdev->prom_name, len);
71 prom_halt();
72 }
73 sdev->num_registers = len / sizeof(struct linux_prom_registers);
74 sdev->ranges_applied = 0;
75 42
76 base = (unsigned long) sdev->reg_addrs[0].phys_addr; 43 base = (unsigned long) sdev->reg_addrs[0].phys_addr;
77 44
78 /* Compute the slot number. */ 45 /* Compute the slot number. */
79 if (base >= SUN_SBUS_BVADDR && sparc_cpu_model == sun4m) { 46 if (base >= SUN_SBUS_BVADDR && sparc_cpu_model == sun4m)
80 sdev->slot = sbus_dev_slot(base); 47 sdev->slot = sbus_dev_slot(base);
81 } else { 48 else
82 sdev->slot = sdev->reg_addrs[0].which_io; 49 sdev->slot = sdev->reg_addrs[0].which_io;
83 } 50 }
84 51
85no_regs:
86 len = prom_getproperty(prom_node, "ranges", 52 len = prom_getproperty(prom_node, "ranges",
87 (char *)sdev->device_ranges, 53 (char *)sdev->device_ranges,
88 sizeof(sdev->device_ranges)); 54 sizeof(sdev->device_ranges));
89 if (len == -1) { 55 sdev->num_device_ranges = 0;
90 sdev->num_device_ranges = 0; 56 if (len != -1)
91 goto no_ranges; 57 sdev->num_device_ranges =
92 } 58 len / sizeof(struct linux_prom_ranges);
93 if (len % sizeof(struct linux_prom_ranges)) {
94 prom_printf("fill_sbus_device: proplen for ranges of %s "
95 " was %d, need multiple of %d\n",
96 sdev->prom_name, len,
97 (int) sizeof(struct linux_prom_ranges));
98 prom_halt();
99 }
100 if (len > (sizeof(struct linux_prom_ranges) * PROMREG_MAX)) {
101 prom_printf("fill_sbus_device: Too many range properties "
102 "for device %s, len=%d\n",
103 sdev->prom_name, len);
104 prom_halt();
105 }
106 sdev->num_device_ranges =
107 len / sizeof(struct linux_prom_ranges);
108 59
109no_ranges: 60 sbus_fill_device_irq(sdev);
110 /* XXX Unfortunately, IRQ issues are very arch specific.
111 * XXX Pull this crud out into an arch specific area
112 * XXX at some point. -DaveM
113 */
114#ifdef CONFIG_SPARC64
115 len = prom_getproperty(prom_node, "interrupts",
116 (char *) irqs, sizeof(irqs));
117 if (len == -1 || len == 0) {
118 sdev->irqs[0] = 0;
119 sdev->num_irqs = 0;
120 } else {
121 unsigned int pri = irqs[0].pri;
122
123 sdev->num_irqs = 1;
124 if (pri < 0x20)
125 pri += sdev->slot * 8;
126
127 sdev->irqs[0] = sbus_build_irq(sdev->bus, pri);
128 }
129#endif /* CONFIG_SPARC64 */
130
131#ifdef CONFIG_SPARC32
132 len = prom_getproperty(prom_node, "intr",
133 (char *)irqs, sizeof(irqs));
134 if (len != -1) {
135 sdev->num_irqs = len / 8;
136 if (sdev->num_irqs == 0) {
137 sdev->irqs[0] = 0;
138 } else if (sparc_cpu_model == sun4d) {
139 extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq);
140
141 for (len = 0; len < sdev->num_irqs; len++)
142 sdev->irqs[len] = sun4d_build_irq(sdev, irqs[len].pri);
143 } else {
144 for (len = 0; len < sdev->num_irqs; len++)
145 sdev->irqs[len] = irqs[len].pri;
146 }
147 } else {
148 /* No "intr" node found-- check for "interrupts" node.
149 * This node contains SBus interrupt levels, not IPLs
150 * as in "intr", and no vector values. We convert
151 * SBus interrupt levels to PILs (platform specific).
152 */
153 len = prom_getproperty(prom_node, "interrupts",
154 (char *)interrupts, sizeof(interrupts));
155 if (len == -1) {
156 sdev->irqs[0] = 0;
157 sdev->num_irqs = 0;
158 } else {
159 sdev->num_irqs = len / sizeof(int);
160 for (len = 0; len < sdev->num_irqs; len++) {
161 sdev->irqs[len] = sbint_to_irq(sdev, interrupts[len]);
162 }
163 }
164 }
165#endif /* CONFIG_SPARC32 */
166} 61}
167 62
168/* This routine gets called from whoever needs the sbus first, to scan 63/* This routine gets called from whoever needs the sbus first, to scan