aboutsummaryrefslogtreecommitdiff
path: root/arch/sparc/kernel/ioport.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/kernel/ioport.c')
-rw-r--r--arch/sparc/kernel/ioport.c131
1 files changed, 130 insertions, 1 deletions
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index f9ff2973484..ae4c667c906 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -39,6 +39,8 @@
#include <asm/io.h>
#include <asm/vaddrs.h>
#include <asm/oplib.h>
+#include <asm/prom.h>
+#include <asm/sbus.h>
#include <asm/page.h>
#include <asm/pgalloc.h>
#include <asm/dma.h>
@@ -224,10 +226,54 @@ static void _sparc_free_io(struct resource *res)
#ifdef CONFIG_SBUS
-void sbus_set_sbus64(struct sbus_dev *sdev, int x) {
+void sbus_set_sbus64(struct sbus_dev *sdev, int x)
+{
printk("sbus_set_sbus64: unsupported\n");
}
+extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq);
+void __init sbus_fill_device_irq(struct sbus_dev *sdev)
+{
+ struct linux_prom_irqs irqs[PROMINTR_MAX];
+ int len;
+
+ len = prom_getproperty(sdev->prom_node, "intr",
+ (char *)irqs, sizeof(irqs));
+ if (len != -1) {
+ sdev->num_irqs = len / 8;
+ if (sdev->num_irqs == 0) {
+ sdev->irqs[0] = 0;
+ } else if (sparc_cpu_model == sun4d) {
+ for (len = 0; len < sdev->num_irqs; len++)
+ sdev->irqs[len] =
+ sun4d_build_irq(sdev, irqs[len].pri);
+ } else {
+ for (len = 0; len < sdev->num_irqs; len++)
+ sdev->irqs[len] = irqs[len].pri;
+ }
+ } else {
+ int interrupts[PROMINTR_MAX];
+
+ /* No "intr" node found-- check for "interrupts" node.
+ * This node contains SBus interrupt levels, not IPLs
+ * as in "intr", and no vector values. We convert
+ * SBus interrupt levels to PILs (platform specific).
+ */
+ len = prom_getproperty(sdev->prom_node, "interrupts",
+ (char *)interrupts, sizeof(interrupts));
+ if (len == -1) {
+ sdev->irqs[0] = 0;
+ sdev->num_irqs = 0;
+ } else {
+ sdev->num_irqs = len / sizeof(int);
+ for (len = 0; len < sdev->num_irqs; len++) {
+ sdev->irqs[len] =
+ sbint_to_irq(sdev, interrupts[len]);
+ }
+ }
+ }
+}
+
/*
* Allocate a chunk of memory suitable for DMA.
* Typically devices use them for control blocks.
@@ -414,6 +460,89 @@ void sbus_dma_sync_sg_for_device(struct sbus_dev *sdev, struct scatterlist *sg,
{
printk("sbus_dma_sync_sg_for_device: not implemented yet\n");
}
+
+/* Support code for sbus_init(). */
+/*
+ * XXX This functions appears to be a distorted version of
+ * prom_sbus_ranges_init(), with all sun4d stuff cut away.
+ * Ask DaveM what is going on here, how is sun4d supposed to work... XXX
+ */
+/* added back sun4d patch from Thomas Bogendoerfer - should be OK (crn) */
+void __init sbus_arch_bus_ranges_init(struct device_node *pn, struct sbus_bus *sbus)
+{
+ int parent_node = pn->node;
+
+ if (sparc_cpu_model == sun4d) {
+ struct linux_prom_ranges iounit_ranges[PROMREG_MAX];
+ int num_iounit_ranges, len;
+
+ len = prom_getproperty(parent_node, "ranges",
+ (char *) iounit_ranges,
+ sizeof (iounit_ranges));
+ if (len != -1) {
+ num_iounit_ranges =
+ (len / sizeof(struct linux_prom_ranges));
+ prom_adjust_ranges(sbus->sbus_ranges,
+ sbus->num_sbus_ranges,
+ iounit_ranges, num_iounit_ranges);
+ }
+ }
+}
+
+void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp)
+{
+ struct device_node *parent = dp->parent;
+
+ if (sparc_cpu_model != sun4d &&
+ parent != NULL &&
+ !strcmp(parent->name, "iommu")) {
+ extern void iommu_init(int iommu_node, struct sbus_bus *sbus);
+
+ iommu_init(parent->node, sbus);
+ }
+
+ if (sparc_cpu_model == sun4d) {
+ extern void iounit_init(int sbi_node, int iounit_node,
+ struct sbus_bus *sbus);
+
+ iounit_init(dp->node, parent->node, sbus);
+ }
+}
+
+void __init sbus_setup_arch_props(struct sbus_bus *sbus, struct device_node *dp)
+{
+ if (sparc_cpu_model == sun4d) {
+ struct device_node *parent = dp->parent;
+
+ sbus->devid = of_getintprop_default(parent, "device-id", 0);
+ sbus->board = of_getintprop_default(parent, "board#", 0);
+ }
+}
+
+int __init sbus_arch_preinit(void)
+{
+ extern void register_proc_sparc_ioport(void);
+
+ register_proc_sparc_ioport();
+
+#ifdef CONFIG_SUN4
+ {
+ extern void sun4_dvma_init(void);
+ sun4_dvma_init();
+ }
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+void __init sbus_arch_postinit(void)
+{
+ if (sparc_cpu_model == sun4d) {
+ extern void sun4d_init_sbi_irq(void);
+ sun4d_init_sbi_irq();
+ }
+}
#endif /* CONFIG_SBUS */
#ifdef CONFIG_PCI