aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/sparc/kernel/ioport.c46
-rw-r--r--arch/sparc64/kernel/sbus.c21
-rw-r--r--drivers/sbus/sbus.c143
-rw-r--r--include/asm-sparc/sbus.h1
-rw-r--r--include/asm-sparc64/sbus.h1
5 files changed, 87 insertions, 125 deletions
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index f9ff29734848..00cf41182912 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -224,10 +224,54 @@ static void _sparc_free_io(struct resource *res)
224 224
225#ifdef CONFIG_SBUS 225#ifdef CONFIG_SBUS
226 226
227void sbus_set_sbus64(struct sbus_dev *sdev, int x) { 227void sbus_set_sbus64(struct sbus_dev *sdev, int x)
228{
228 printk("sbus_set_sbus64: unsupported\n"); 229 printk("sbus_set_sbus64: unsupported\n");
229} 230}
230 231
232extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq);
233void __init sbus_fill_device_irq(struct sbus_dev *sdev)
234{
235 struct linux_prom_irqs irqs[PROMINTR_MAX];
236 int len;
237
238 len = prom_getproperty(sdev->prom_node, "intr",
239 (char *)irqs, sizeof(irqs));
240 if (len != -1) {
241 sdev->num_irqs = len / 8;
242 if (sdev->num_irqs == 0) {
243 sdev->irqs[0] = 0;
244 } else if (sparc_cpu_model == sun4d) {
245 for (len = 0; len < sdev->num_irqs; len++)
246 sdev->irqs[len] =
247 sun4d_build_irq(sdev, irqs[len].pri);
248 } else {
249 for (len = 0; len < sdev->num_irqs; len++)
250 sdev->irqs[len] = irqs[len].pri;
251 }
252 } else {
253 int interrupts[PROMINTR_MAX];
254
255 /* No "intr" node found-- check for "interrupts" node.
256 * This node contains SBus interrupt levels, not IPLs
257 * as in "intr", and no vector values. We convert
258 * SBus interrupt levels to PILs (platform specific).
259 */
260 len = prom_getproperty(sdev->prom_node, "interrupts",
261 (char *)interrupts, sizeof(interrupts));
262 if (len == -1) {
263 sdev->irqs[0] = 0;
264 sdev->num_irqs = 0;
265 } else {
266 sdev->num_irqs = len / sizeof(int);
267 for (len = 0; len < sdev->num_irqs; len++) {
268 sdev->irqs[len] =
269 sbint_to_irq(sdev, interrupts[len]);
270 }
271 }
272 }
273}
274
231/* 275/*
232 * Allocate a chunk of memory suitable for DMA. 276 * Allocate a chunk of memory suitable for DMA.
233 * Typically devices use them for control blocks. 277 * Typically devices use them for control blocks.
diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c
index 8812417247d4..8f7877ac858f 100644
--- a/arch/sparc64/kernel/sbus.c
+++ b/arch/sparc64/kernel/sbus.c
@@ -1225,3 +1225,24 @@ void __init sbus_iommu_init(int prom_node, struct sbus_bus *sbus)
1225 1225
1226 sysio_register_error_handlers(sbus); 1226 sysio_register_error_handlers(sbus);
1227} 1227}
1228
1229void sbus_fill_device_irq(struct sbus_dev *sdev)
1230{
1231 struct linux_prom_irqs irqs[PROMINTR_MAX];
1232 int len;
1233
1234 len = prom_getproperty(sdev->prom_node, "interrupts",
1235 (char *) irqs, sizeof(irqs));
1236 if (len == -1 || len == 0) {
1237 sdev->irqs[0] = 0;
1238 sdev->num_irqs = 0;
1239 } else {
1240 unsigned int pri = irqs[0].pri;
1241
1242 sdev->num_irqs = 1;
1243 if (pri < 0x20)
1244 pri += sdev->slot * 8;
1245
1246 sdev->irqs[0] = sbus_build_irq(sdev->bus, pri);
1247 }
1248}
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
diff --git a/include/asm-sparc/sbus.h b/include/asm-sparc/sbus.h
index a13cddcecec5..76654fa23091 100644
--- a/include/asm-sparc/sbus.h
+++ b/include/asm-sparc/sbus.h
@@ -102,6 +102,7 @@ sbus_is_slave(struct sbus_dev *dev)
102#define sbus_can_dma_64bit(sdev) (0) /* actually, sparc_cpu_model==sun4d */ 102#define sbus_can_dma_64bit(sdev) (0) /* actually, sparc_cpu_model==sun4d */
103#define sbus_can_burst64(sdev) (0) /* actually, sparc_cpu_model==sun4d */ 103#define sbus_can_burst64(sdev) (0) /* actually, sparc_cpu_model==sun4d */
104extern void sbus_set_sbus64(struct sbus_dev *, int); 104extern void sbus_set_sbus64(struct sbus_dev *, int);
105extern void sbus_fill_device_irq(struct sbus_dev *);
105 106
106/* These yield IOMMU mappings in consistent mode. */ 107/* These yield IOMMU mappings in consistent mode. */
107extern void *sbus_alloc_consistent(struct sbus_dev *, long, u32 *dma_addrp); 108extern void *sbus_alloc_consistent(struct sbus_dev *, long, u32 *dma_addrp);
diff --git a/include/asm-sparc64/sbus.h b/include/asm-sparc64/sbus.h
index 48279e10f385..ca2054da2430 100644
--- a/include/asm-sparc64/sbus.h
+++ b/include/asm-sparc64/sbus.h
@@ -95,6 +95,7 @@ extern struct sbus_bus *sbus_root;
95#define sbus_can_dma_64bit(sdev) (1) 95#define sbus_can_dma_64bit(sdev) (1)
96#define sbus_can_burst64(sdev) (1) 96#define sbus_can_burst64(sdev) (1)
97extern void sbus_set_sbus64(struct sbus_dev *, int); 97extern void sbus_set_sbus64(struct sbus_dev *, int);
98extern void sbus_fill_device_irq(struct sbus_dev *);
98 99
99/* These yield IOMMU mappings in consistent mode. */ 100/* These yield IOMMU mappings in consistent mode. */
100extern void *sbus_alloc_consistent(struct sbus_dev *, size_t, dma_addr_t *dma_addrp); 101extern void *sbus_alloc_consistent(struct sbus_dev *, size_t, dma_addr_t *dma_addrp);