- use dvma code inside dma api for SUN3/SUN3X
- make ioremap use mappings through tt1 for SUN3x
- add platform device for converted sun3x_esp driver
Signed-off-by: Thomas Bogendoerfer <tsbogend@xxxxxxxxxxxxxxxx>
---
This is the first step to get Sun3x back to life. I have a working
kernel with these changes (tested on a Sun 3/80). The missing pieces
are for the console driver, which is still too hackish to submit, yet.
arch/m68k/kernel/dma.c | 43 +++++++++++++++++++++++++++++++++++++++-
arch/m68k/mm/kmap.c | 24 ++++++++++++++++-----
arch/m68k/sun3x/config.c | 31 ++++++++++++++++++++++++++++
include/asm-m68k/dma-mapping.h | 25 ++++++++++++++++++----
include/asm-m68k/sun3xprom.h | 5 ++++
5 files changed, 116 insertions(+), 12 deletions(-)
diff --git a/arch/m68k/kernel/dma.c b/arch/m68k/kernel/dma.c
index 6f8c080..0b9b818 100644
--- a/arch/m68k/kernel/dma.c
+++ b/arch/m68k/kernel/dma.c
@@ -13,6 +13,7 @@
#include <linux/vmalloc.h>
#include <asm/pgalloc.h>
+#include <asm/dvma.h>
void *dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *handle, gfp_t flag)
@@ -31,7 +32,11 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
if (!page)
return NULL;
- *handle = page_to_phys(page);
+ if (MACH_IS_SUN3 || MACH_IS_SUN3X)
+ *handle = dvma_map(page_to_phys(page), size);
+ else
+ *handle = page_to_phys(page);
+
map = kmalloc(sizeof(struct page *) << order, flag & ~__GFP_DMA);
if (!map) {
__free_pages(page, order);
@@ -62,6 +67,8 @@ void dma_free_coherent(struct device *dev, size_t size,
void *addr, dma_addr_t handle)
{
pr_debug("dma_free_coherent: %p, %x\n", addr, handle);
+ if (MACH_IS_SUN3 || MACH_IS_SUN3X)
+ dvma_unmap((void *)handle);
vfree(addr);
}
EXPORT_SYMBOL(dma_free_coherent);
@@ -100,6 +107,8 @@ dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size,
dma_addr_t handle = virt_to_bus(addr);
dma_sync_single_for_device(dev, handle, size, dir);
+ if (MACH_IS_SUN3 || MACH_IS_SUN3X)
+ handle = dvma_map(handle, size);
return handle;
}
EXPORT_SYMBOL(dma_map_single);
@@ -111,6 +120,8 @@ dma_addr_t dma_map_page(struct device *dev, struct page *page,
dma_addr_t handle = page_to_phys(page) + offset;
dma_sync_single_for_device(dev, handle, size, dir);
+ if (MACH_IS_SUN3 || MACH_IS_SUN3X)
+ handle = dvma_map(handle, size);
return handle;
}
EXPORT_SYMBOL(dma_map_page);
@@ -123,7 +134,37 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
for (i = 0; i < nents; sg++, i++) {
sg->dma_address = sg_phys(sg);
dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
+ if (MACH_IS_SUN3 || MACH_IS_SUN3X)
+ sg->dma_address = dvma_map(sg->dma_address, sg->length);
}
return nents;
}
EXPORT_SYMBOL(dma_map_sg);
+
+#if defined(CONFIG_SUN3) || defined(CONFIG_SUN3X)
+void dma_unmap_single(struct device *dev, dma_addr_t addr,
+ size_t size, enum dma_data_direction dir)
+{
+ if (MACH_IS_SUN3 || MACH_IS_SUN3X)
+ dvma_unmap((void *)addr);
+}
+
+
+void dma_unmap_page(struct device *dev, dma_addr_t addr,
+ size_t size, enum dma_data_direction dir)
+{
+ if (MACH_IS_SUN3 || MACH_IS_SUN3X)
+ dvma_unmap((void *)addr);
+}
+
+
+void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction dir)
+{
+ int i;
+
+ if (MACH_IS_SUN3 || MACH_IS_SUN3X)
+ for (i = 0; i < nents; sg++, i++)
+ dvma_unmap((void *)sg->dma_address);
+}
+#endif
diff --git a/arch/m68k/mm/kmap.c b/arch/m68k/mm/kmap.c
index 46b7d60..e76cb5e 100644
--- a/arch/m68k/mm/kmap.c
+++ b/arch/m68k/mm/kmap.c
@@ -124,6 +124,13 @@ void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cachefla
return (void __iomem *)physaddr;
}
#endif
+#ifdef CONFIG_SUN3X
+ if (MACH_IS_SUN3X) {
+ if ((physaddr >= 0x40000000) && (physaddr + size < 0x80000000)
+ && (cacheflag == IOMAP_NOCACHE_SER))
+ return (void __iomem *)physaddr;
+ }
+#endif
#ifdef DEBUG
printk("ioremap: 0x%lx,0x%lx(%d) - ", physaddr, size, cacheflag);
@@ -228,13 +235,18 @@ EXPORT_SYMBOL(__ioremap);
void iounmap(void __iomem *addr)
{
#ifdef CONFIG_AMIGA
- if ((!MACH_IS_AMIGA) ||
- (((unsigned long)addr < 0x40000000) ||
- ((unsigned long)addr > 0x60000000)))
- free_io_area((__force void *)addr);
-#else
- free_io_area((__force void *)addr);
+ if (MACH_IS_AMIGA &&
+ (((unsigned long)addr >= 0x40000000) &&
+ ((unsigned long)addr < 0x60000000)))
+ return;
#endif
+#ifdef CONFIG_SUN3X
+ if (MACH_IS_SUN3X &&
+ (((unsigned long)addr >= 0x40000000) &&
+ ((unsigned long)addr < 0x80000000)))
+ return;
+#endif
+ free_io_area((__force void *)addr);
}
EXPORT_SYMBOL(iounmap);
diff --git a/arch/m68k/sun3x/config.c b/arch/m68k/sun3x/config.c
index 9878917..e021873 100644
--- a/arch/m68k/sun3x/config.c
+++ b/arch/m68k/sun3x/config.c
@@ -10,6 +10,7 @@
#include <linux/mm.h>
#include <linux/console.h>
#include <linux/init.h>
+#include <linux/platform_device.h>
#include <asm/system.h>
#include <asm/machdep.h>
@@ -21,6 +22,30 @@
#include "time.h"
+static struct resource sun3x_esp_rsrc[] = {
+ {
+ .start = SUN3X_ESP_BASE,
+ .end = SUN3X_ESP_BASE + 31,
+ .flags = IORESOURCE_MEM
+ },
+ {
+ .start = SUN3X_ESP_DMA,
+ .end = SUN3X_ESP_DMA + 15,
+ .flags = IORESOURCE_MEM
+ },
+ {
+ .start = 2,
+ .end = 2,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+static struct platform_device sun3x_esp_pdev = {
+ .name = "sun3x_esp",
+ .num_resources = ARRAY_SIZE(sun3x_esp_rsrc),
+ .resource = sun3x_esp_rsrc
+};
+
volatile char *clock_va;
extern volatile unsigned char *sun3_intreg;
@@ -82,6 +107,12 @@ void __init config_sun3x(void)
break;
}
#endif
+ add_preferred_console("ttyS", 0, "9600");
+}
+static int __init sun3x_devinit(void)
+{
+ platform_device_register(&sun3x_esp_pdev);
}
+device_initcall(sun3x_devinit);
diff --git a/include/asm-m68k/dma-mapping.h b/include/asm-m68k/dma-mapping.h
index a26cdeb..72e44d9 100644
--- a/include/asm-m68k/dma-mapping.h
+++ b/include/asm-m68k/dma-mapping.h
@@ -49,25 +49,40 @@ static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
extern dma_addr_t dma_map_single(struct device *, void *, size_t,
enum dma_data_direction);
+
+extern dma_addr_t dma_map_page(struct device *, struct page *,
+ unsigned long, size_t size,
+ enum dma_data_direction);
+
+extern int dma_map_sg(struct device *, struct scatterlist *, int,
+ enum dma_data_direction);
+
+#if defined(CONFIG_SUN3) || defined(CONFIG_SUN3X)
+extern void dma_unmap_single(struct device *dev, dma_addr_t addr,
+ size_t size, enum dma_data_direction dir);
+
+extern void dma_unmap_page(struct device *dev, dma_addr_t addr,
+ size_t size, enum dma_data_direction dir);
+
+extern void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction dir);
+
+#else
static inline void dma_unmap_single(struct device *dev, dma_addr_t addr,
size_t size, enum dma_data_direction dir)
{
}
-extern dma_addr_t dma_map_page(struct device *, struct page *,
- unsigned long, size_t size,
- enum dma_data_direction);
static inline void dma_unmap_page(struct device *dev, dma_addr_t address,
size_t size, enum dma_data_direction dir)
{
}
-extern int dma_map_sg(struct device *, struct scatterlist *, int,
- enum dma_data_direction);
static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
int nhwentries, enum dma_data_direction dir)
{
}
+#endif
extern void dma_sync_single_for_device(struct device *, dma_addr_t, size_t,
enum dma_data_direction);
diff --git a/include/asm-m68k/sun3xprom.h b/include/asm-m68k/sun3xprom.h
index 6735efc..15bd5c0 100644
--- a/include/asm-m68k/sun3xprom.h
+++ b/include/asm-m68k/sun3xprom.h
@@ -25,6 +25,11 @@ unsigned long sun3x_prom_ptov(unsigned long pa, unsigned long size);
#define SUN3X_IDPROM 0x640007d8
#define SUN3X_VIDEO_BASE 0x50400000
#define SUN3X_VIDEO_REGS 0x50300000
+#define SUN3X_ESP_BASE 0x66000000
+#define SUN3X_ESP_DMA 0x66001000
+#define SUN3X_FDC 0x6e000000
+#define SUN3X_FDC_FCR 0x6e000400
+#define SUN3X_FDC_FVR 0x6e000800
/* vector table */
#define SUN3X_PROM_BASE 0xfefe0000