- 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 - To unsubscribe from this list: send the line "unsubscribe linux-m68k" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html