diff options
-rw-r--r-- | arch/sparc/kernel/ioport.c | 46 | ||||
-rw-r--r-- | arch/sparc64/kernel/sbus.c | 21 | ||||
-rw-r--r-- | drivers/sbus/sbus.c | 143 | ||||
-rw-r--r-- | include/asm-sparc/sbus.h | 1 | ||||
-rw-r--r-- | include/asm-sparc64/sbus.h | 1 |
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 | ||
227 | void sbus_set_sbus64(struct sbus_dev *sdev, int x) { | 227 | void 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 | ||
232 | extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq); | ||
233 | void __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 | |||
1229 | void 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 | ||
20 | struct sbus_bus *sbus_root = NULL; | 19 | struct sbus_bus *sbus_root; |
21 | |||
22 | static struct linux_prom_irqs irqs[PROMINTR_MAX] __initdata = { { 0 } }; | ||
23 | #ifdef CONFIG_SPARC32 | ||
24 | static int interrupts[PROMINTR_MAX] __initdata = { 0 }; | ||
25 | #endif | ||
26 | 20 | ||
27 | #ifdef CONFIG_PCI | 21 | #ifdef CONFIG_PCI |
28 | extern int pcic_present(void); | 22 | extern 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 | |||
43 | static void __init fill_sbus_device(int prom_node, struct sbus_dev *sdev) | 25 | static 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 | ||
85 | no_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 | ||
109 | no_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 */ |
104 | extern void sbus_set_sbus64(struct sbus_dev *, int); | 104 | extern void sbus_set_sbus64(struct sbus_dev *, int); |
105 | extern 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. */ |
107 | extern void *sbus_alloc_consistent(struct sbus_dev *, long, u32 *dma_addrp); | 108 | extern 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) |
97 | extern void sbus_set_sbus64(struct sbus_dev *, int); | 97 | extern void sbus_set_sbus64(struct sbus_dev *, int); |
98 | extern 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. */ |
100 | extern void *sbus_alloc_consistent(struct sbus_dev *, size_t, dma_addr_t *dma_addrp); | 101 | extern void *sbus_alloc_consistent(struct sbus_dev *, size_t, dma_addr_t *dma_addrp); |