18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * linux/arch/arm/mach-rpc/dma.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 1998 Russell King 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * DMA functions specific to RiscPC architecture 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci#include <linux/mman.h> 108c2ecf20Sopenharmony_ci#include <linux/init.h> 118c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 128c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 138c2ecf20Sopenharmony_ci#include <linux/io.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <asm/page.h> 168c2ecf20Sopenharmony_ci#include <asm/dma.h> 178c2ecf20Sopenharmony_ci#include <asm/fiq.h> 188c2ecf20Sopenharmony_ci#include <asm/irq.h> 198c2ecf20Sopenharmony_ci#include <mach/hardware.h> 208c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#include <asm/mach/dma.h> 238c2ecf20Sopenharmony_ci#include <asm/hardware/iomd.h> 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistruct iomd_dma { 268c2ecf20Sopenharmony_ci struct dma_struct dma; 278c2ecf20Sopenharmony_ci void __iomem *base; /* Controller base address */ 288c2ecf20Sopenharmony_ci int irq; /* Controller IRQ */ 298c2ecf20Sopenharmony_ci unsigned int state; 308c2ecf20Sopenharmony_ci dma_addr_t cur_addr; 318c2ecf20Sopenharmony_ci unsigned int cur_len; 328c2ecf20Sopenharmony_ci dma_addr_t dma_addr; 338c2ecf20Sopenharmony_ci unsigned int dma_len; 348c2ecf20Sopenharmony_ci}; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#if 0 378c2ecf20Sopenharmony_citypedef enum { 388c2ecf20Sopenharmony_ci dma_size_8 = 1, 398c2ecf20Sopenharmony_ci dma_size_16 = 2, 408c2ecf20Sopenharmony_ci dma_size_32 = 4, 418c2ecf20Sopenharmony_ci dma_size_128 = 16 428c2ecf20Sopenharmony_ci} dma_size_t; 438c2ecf20Sopenharmony_ci#endif 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci#define TRANSFER_SIZE 2 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci#define CURA (0) 488c2ecf20Sopenharmony_ci#define ENDA (IOMD_IO0ENDA - IOMD_IO0CURA) 498c2ecf20Sopenharmony_ci#define CURB (IOMD_IO0CURB - IOMD_IO0CURA) 508c2ecf20Sopenharmony_ci#define ENDB (IOMD_IO0ENDB - IOMD_IO0CURA) 518c2ecf20Sopenharmony_ci#define CR (IOMD_IO0CR - IOMD_IO0CURA) 528c2ecf20Sopenharmony_ci#define ST (IOMD_IO0ST - IOMD_IO0CURA) 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_cistatic void iomd_get_next_sg(struct iomd_dma *idma) 558c2ecf20Sopenharmony_ci{ 568c2ecf20Sopenharmony_ci unsigned long end, offset, flags = 0; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci if (idma->dma.sg) { 598c2ecf20Sopenharmony_ci idma->cur_addr = idma->dma_addr; 608c2ecf20Sopenharmony_ci offset = idma->cur_addr & ~PAGE_MASK; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci end = offset + idma->dma_len; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci if (end > PAGE_SIZE) 658c2ecf20Sopenharmony_ci end = PAGE_SIZE; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci if (offset + TRANSFER_SIZE >= end) 688c2ecf20Sopenharmony_ci flags |= DMA_END_L; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci idma->cur_len = end - TRANSFER_SIZE; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci idma->dma_len -= end - offset; 738c2ecf20Sopenharmony_ci idma->dma_addr += end - offset; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci if (idma->dma_len == 0) { 768c2ecf20Sopenharmony_ci if (idma->dma.sgcount > 1) { 778c2ecf20Sopenharmony_ci idma->dma.sg = sg_next(idma->dma.sg); 788c2ecf20Sopenharmony_ci idma->dma_addr = idma->dma.sg->dma_address; 798c2ecf20Sopenharmony_ci idma->dma_len = idma->dma.sg->length; 808c2ecf20Sopenharmony_ci idma->dma.sgcount--; 818c2ecf20Sopenharmony_ci } else { 828c2ecf20Sopenharmony_ci idma->dma.sg = NULL; 838c2ecf20Sopenharmony_ci flags |= DMA_END_S; 848c2ecf20Sopenharmony_ci } 858c2ecf20Sopenharmony_ci } 868c2ecf20Sopenharmony_ci } else { 878c2ecf20Sopenharmony_ci flags = DMA_END_S | DMA_END_L; 888c2ecf20Sopenharmony_ci idma->cur_addr = 0; 898c2ecf20Sopenharmony_ci idma->cur_len = 0; 908c2ecf20Sopenharmony_ci } 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci idma->cur_len |= flags; 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic irqreturn_t iomd_dma_handle(int irq, void *dev_id) 968c2ecf20Sopenharmony_ci{ 978c2ecf20Sopenharmony_ci struct iomd_dma *idma = dev_id; 988c2ecf20Sopenharmony_ci void __iomem *base = idma->base; 998c2ecf20Sopenharmony_ci unsigned int state = idma->state; 1008c2ecf20Sopenharmony_ci unsigned int status, cur, end; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci do { 1038c2ecf20Sopenharmony_ci status = readb(base + ST); 1048c2ecf20Sopenharmony_ci if (!(status & DMA_ST_INT)) 1058c2ecf20Sopenharmony_ci goto out; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci if ((state ^ status) & DMA_ST_AB) 1088c2ecf20Sopenharmony_ci iomd_get_next_sg(idma); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci // This efficiently implements state = OFL != AB ? AB : 0 1118c2ecf20Sopenharmony_ci state = ((status >> 2) ^ status) & DMA_ST_AB; 1128c2ecf20Sopenharmony_ci if (state) { 1138c2ecf20Sopenharmony_ci cur = CURA; 1148c2ecf20Sopenharmony_ci end = ENDA; 1158c2ecf20Sopenharmony_ci } else { 1168c2ecf20Sopenharmony_ci cur = CURB; 1178c2ecf20Sopenharmony_ci end = ENDB; 1188c2ecf20Sopenharmony_ci } 1198c2ecf20Sopenharmony_ci writel(idma->cur_addr, base + cur); 1208c2ecf20Sopenharmony_ci writel(idma->cur_len, base + end); 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci if (status & DMA_ST_OFL && 1238c2ecf20Sopenharmony_ci idma->cur_len == (DMA_END_S|DMA_END_L)) 1248c2ecf20Sopenharmony_ci break; 1258c2ecf20Sopenharmony_ci } while (1); 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci state = ~DMA_ST_AB; 1288c2ecf20Sopenharmony_ci disable_irq_nosync(irq); 1298c2ecf20Sopenharmony_ciout: 1308c2ecf20Sopenharmony_ci idma->state = state; 1318c2ecf20Sopenharmony_ci return IRQ_HANDLED; 1328c2ecf20Sopenharmony_ci} 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_cistatic int iomd_request_dma(unsigned int chan, dma_t *dma) 1358c2ecf20Sopenharmony_ci{ 1368c2ecf20Sopenharmony_ci struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma); 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci return request_irq(idma->irq, iomd_dma_handle, 1398c2ecf20Sopenharmony_ci 0, idma->dma.device_id, idma); 1408c2ecf20Sopenharmony_ci} 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cistatic void iomd_free_dma(unsigned int chan, dma_t *dma) 1438c2ecf20Sopenharmony_ci{ 1448c2ecf20Sopenharmony_ci struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma); 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci free_irq(idma->irq, idma); 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_cistatic struct device isa_dma_dev = { 1508c2ecf20Sopenharmony_ci .init_name = "fallback device", 1518c2ecf20Sopenharmony_ci .coherent_dma_mask = ~(dma_addr_t)0, 1528c2ecf20Sopenharmony_ci .dma_mask = &isa_dma_dev.coherent_dma_mask, 1538c2ecf20Sopenharmony_ci}; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_cistatic void iomd_enable_dma(unsigned int chan, dma_t *dma) 1568c2ecf20Sopenharmony_ci{ 1578c2ecf20Sopenharmony_ci struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma); 1588c2ecf20Sopenharmony_ci void __iomem *base = idma->base; 1598c2ecf20Sopenharmony_ci unsigned int ctrl = TRANSFER_SIZE | DMA_CR_E; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci if (idma->dma.invalid) { 1628c2ecf20Sopenharmony_ci idma->dma.invalid = 0; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci /* 1658c2ecf20Sopenharmony_ci * Cope with ISA-style drivers which expect cache 1668c2ecf20Sopenharmony_ci * coherence. 1678c2ecf20Sopenharmony_ci */ 1688c2ecf20Sopenharmony_ci if (!idma->dma.sg) { 1698c2ecf20Sopenharmony_ci idma->dma.sg = &idma->dma.buf; 1708c2ecf20Sopenharmony_ci idma->dma.sgcount = 1; 1718c2ecf20Sopenharmony_ci idma->dma.buf.length = idma->dma.count; 1728c2ecf20Sopenharmony_ci idma->dma.buf.dma_address = dma_map_single(&isa_dma_dev, 1738c2ecf20Sopenharmony_ci idma->dma.addr, idma->dma.count, 1748c2ecf20Sopenharmony_ci idma->dma.dma_mode == DMA_MODE_READ ? 1758c2ecf20Sopenharmony_ci DMA_FROM_DEVICE : DMA_TO_DEVICE); 1768c2ecf20Sopenharmony_ci } 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci idma->dma_addr = idma->dma.sg->dma_address; 1798c2ecf20Sopenharmony_ci idma->dma_len = idma->dma.sg->length; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci writeb(DMA_CR_C, base + CR); 1828c2ecf20Sopenharmony_ci idma->state = DMA_ST_AB; 1838c2ecf20Sopenharmony_ci } 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci if (idma->dma.dma_mode == DMA_MODE_READ) 1868c2ecf20Sopenharmony_ci ctrl |= DMA_CR_D; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci writeb(ctrl, base + CR); 1898c2ecf20Sopenharmony_ci enable_irq(idma->irq); 1908c2ecf20Sopenharmony_ci} 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_cistatic void iomd_disable_dma(unsigned int chan, dma_t *dma) 1938c2ecf20Sopenharmony_ci{ 1948c2ecf20Sopenharmony_ci struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma); 1958c2ecf20Sopenharmony_ci void __iomem *base = idma->base; 1968c2ecf20Sopenharmony_ci unsigned long flags; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci local_irq_save(flags); 1998c2ecf20Sopenharmony_ci if (idma->state != ~DMA_ST_AB) 2008c2ecf20Sopenharmony_ci disable_irq(idma->irq); 2018c2ecf20Sopenharmony_ci writeb(0, base + CR); 2028c2ecf20Sopenharmony_ci local_irq_restore(flags); 2038c2ecf20Sopenharmony_ci} 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_cistatic int iomd_set_dma_speed(unsigned int chan, dma_t *dma, int cycle) 2068c2ecf20Sopenharmony_ci{ 2078c2ecf20Sopenharmony_ci int tcr, speed; 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci if (cycle < 188) 2108c2ecf20Sopenharmony_ci speed = 3; 2118c2ecf20Sopenharmony_ci else if (cycle <= 250) 2128c2ecf20Sopenharmony_ci speed = 2; 2138c2ecf20Sopenharmony_ci else if (cycle < 438) 2148c2ecf20Sopenharmony_ci speed = 1; 2158c2ecf20Sopenharmony_ci else 2168c2ecf20Sopenharmony_ci speed = 0; 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci tcr = iomd_readb(IOMD_DMATCR); 2198c2ecf20Sopenharmony_ci speed &= 3; 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci switch (chan) { 2228c2ecf20Sopenharmony_ci case DMA_0: 2238c2ecf20Sopenharmony_ci tcr = (tcr & ~0x03) | speed; 2248c2ecf20Sopenharmony_ci break; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci case DMA_1: 2278c2ecf20Sopenharmony_ci tcr = (tcr & ~0x0c) | (speed << 2); 2288c2ecf20Sopenharmony_ci break; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci case DMA_2: 2318c2ecf20Sopenharmony_ci tcr = (tcr & ~0x30) | (speed << 4); 2328c2ecf20Sopenharmony_ci break; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci case DMA_3: 2358c2ecf20Sopenharmony_ci tcr = (tcr & ~0xc0) | (speed << 6); 2368c2ecf20Sopenharmony_ci break; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci default: 2398c2ecf20Sopenharmony_ci break; 2408c2ecf20Sopenharmony_ci } 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci iomd_writeb(tcr, IOMD_DMATCR); 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci return speed; 2458c2ecf20Sopenharmony_ci} 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_cistatic struct dma_ops iomd_dma_ops = { 2488c2ecf20Sopenharmony_ci .type = "IOMD", 2498c2ecf20Sopenharmony_ci .request = iomd_request_dma, 2508c2ecf20Sopenharmony_ci .free = iomd_free_dma, 2518c2ecf20Sopenharmony_ci .enable = iomd_enable_dma, 2528c2ecf20Sopenharmony_ci .disable = iomd_disable_dma, 2538c2ecf20Sopenharmony_ci .setspeed = iomd_set_dma_speed, 2548c2ecf20Sopenharmony_ci}; 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_cistatic struct fiq_handler fh = { 2578c2ecf20Sopenharmony_ci .name = "floppydma" 2588c2ecf20Sopenharmony_ci}; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_cistruct floppy_dma { 2618c2ecf20Sopenharmony_ci struct dma_struct dma; 2628c2ecf20Sopenharmony_ci unsigned int fiq; 2638c2ecf20Sopenharmony_ci}; 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_cistatic void floppy_enable_dma(unsigned int chan, dma_t *dma) 2668c2ecf20Sopenharmony_ci{ 2678c2ecf20Sopenharmony_ci struct floppy_dma *fdma = container_of(dma, struct floppy_dma, dma); 2688c2ecf20Sopenharmony_ci void *fiqhandler_start; 2698c2ecf20Sopenharmony_ci unsigned int fiqhandler_length; 2708c2ecf20Sopenharmony_ci struct pt_regs regs; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci if (fdma->dma.sg) 2738c2ecf20Sopenharmony_ci BUG(); 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci if (fdma->dma.dma_mode == DMA_MODE_READ) { 2768c2ecf20Sopenharmony_ci extern unsigned char floppy_fiqin_start, floppy_fiqin_end; 2778c2ecf20Sopenharmony_ci fiqhandler_start = &floppy_fiqin_start; 2788c2ecf20Sopenharmony_ci fiqhandler_length = &floppy_fiqin_end - &floppy_fiqin_start; 2798c2ecf20Sopenharmony_ci } else { 2808c2ecf20Sopenharmony_ci extern unsigned char floppy_fiqout_start, floppy_fiqout_end; 2818c2ecf20Sopenharmony_ci fiqhandler_start = &floppy_fiqout_start; 2828c2ecf20Sopenharmony_ci fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start; 2838c2ecf20Sopenharmony_ci } 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci regs.ARM_r9 = fdma->dma.count; 2868c2ecf20Sopenharmony_ci regs.ARM_r10 = (unsigned long)fdma->dma.addr; 2878c2ecf20Sopenharmony_ci regs.ARM_fp = (unsigned long)FLOPPYDMA_BASE; 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci if (claim_fiq(&fh)) { 2908c2ecf20Sopenharmony_ci printk("floppydma: couldn't claim FIQ.\n"); 2918c2ecf20Sopenharmony_ci return; 2928c2ecf20Sopenharmony_ci } 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci set_fiq_handler(fiqhandler_start, fiqhandler_length); 2958c2ecf20Sopenharmony_ci set_fiq_regs(®s); 2968c2ecf20Sopenharmony_ci enable_fiq(fdma->fiq); 2978c2ecf20Sopenharmony_ci} 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_cistatic void floppy_disable_dma(unsigned int chan, dma_t *dma) 3008c2ecf20Sopenharmony_ci{ 3018c2ecf20Sopenharmony_ci struct floppy_dma *fdma = container_of(dma, struct floppy_dma, dma); 3028c2ecf20Sopenharmony_ci disable_fiq(fdma->fiq); 3038c2ecf20Sopenharmony_ci release_fiq(&fh); 3048c2ecf20Sopenharmony_ci} 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_cistatic int floppy_get_residue(unsigned int chan, dma_t *dma) 3078c2ecf20Sopenharmony_ci{ 3088c2ecf20Sopenharmony_ci struct pt_regs regs; 3098c2ecf20Sopenharmony_ci get_fiq_regs(®s); 3108c2ecf20Sopenharmony_ci return regs.ARM_r9; 3118c2ecf20Sopenharmony_ci} 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_cistatic struct dma_ops floppy_dma_ops = { 3148c2ecf20Sopenharmony_ci .type = "FIQDMA", 3158c2ecf20Sopenharmony_ci .enable = floppy_enable_dma, 3168c2ecf20Sopenharmony_ci .disable = floppy_disable_dma, 3178c2ecf20Sopenharmony_ci .residue = floppy_get_residue, 3188c2ecf20Sopenharmony_ci}; 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci/* 3218c2ecf20Sopenharmony_ci * This is virtual DMA - we don't need anything here. 3228c2ecf20Sopenharmony_ci */ 3238c2ecf20Sopenharmony_cistatic void sound_enable_disable_dma(unsigned int chan, dma_t *dma) 3248c2ecf20Sopenharmony_ci{ 3258c2ecf20Sopenharmony_ci} 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_cistatic struct dma_ops sound_dma_ops = { 3288c2ecf20Sopenharmony_ci .type = "VIRTUAL", 3298c2ecf20Sopenharmony_ci .enable = sound_enable_disable_dma, 3308c2ecf20Sopenharmony_ci .disable = sound_enable_disable_dma, 3318c2ecf20Sopenharmony_ci}; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_cistatic struct iomd_dma iomd_dma[6]; 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_cistatic struct floppy_dma floppy_dma = { 3368c2ecf20Sopenharmony_ci .dma = { 3378c2ecf20Sopenharmony_ci .d_ops = &floppy_dma_ops, 3388c2ecf20Sopenharmony_ci }, 3398c2ecf20Sopenharmony_ci .fiq = FIQ_FLOPPYDATA, 3408c2ecf20Sopenharmony_ci}; 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_cistatic dma_t sound_dma = { 3438c2ecf20Sopenharmony_ci .d_ops = &sound_dma_ops, 3448c2ecf20Sopenharmony_ci}; 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_cistatic int __init rpc_dma_init(void) 3478c2ecf20Sopenharmony_ci{ 3488c2ecf20Sopenharmony_ci unsigned int i; 3498c2ecf20Sopenharmony_ci int ret; 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci iomd_writeb(0, IOMD_IO0CR); 3528c2ecf20Sopenharmony_ci iomd_writeb(0, IOMD_IO1CR); 3538c2ecf20Sopenharmony_ci iomd_writeb(0, IOMD_IO2CR); 3548c2ecf20Sopenharmony_ci iomd_writeb(0, IOMD_IO3CR); 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci iomd_writeb(0xa0, IOMD_DMATCR); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci /* 3598c2ecf20Sopenharmony_ci * Setup DMA channels 2,3 to be for podules 3608c2ecf20Sopenharmony_ci * and channels 0,1 for internal devices 3618c2ecf20Sopenharmony_ci */ 3628c2ecf20Sopenharmony_ci iomd_writeb(DMA_EXT_IO3|DMA_EXT_IO2, IOMD_DMAEXT); 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci iomd_dma[DMA_0].base = IOMD_BASE + IOMD_IO0CURA; 3658c2ecf20Sopenharmony_ci iomd_dma[DMA_0].irq = IRQ_DMA0; 3668c2ecf20Sopenharmony_ci iomd_dma[DMA_1].base = IOMD_BASE + IOMD_IO1CURA; 3678c2ecf20Sopenharmony_ci iomd_dma[DMA_1].irq = IRQ_DMA1; 3688c2ecf20Sopenharmony_ci iomd_dma[DMA_2].base = IOMD_BASE + IOMD_IO2CURA; 3698c2ecf20Sopenharmony_ci iomd_dma[DMA_2].irq = IRQ_DMA2; 3708c2ecf20Sopenharmony_ci iomd_dma[DMA_3].base = IOMD_BASE + IOMD_IO3CURA; 3718c2ecf20Sopenharmony_ci iomd_dma[DMA_3].irq = IRQ_DMA3; 3728c2ecf20Sopenharmony_ci iomd_dma[DMA_S0].base = IOMD_BASE + IOMD_SD0CURA; 3738c2ecf20Sopenharmony_ci iomd_dma[DMA_S0].irq = IRQ_DMAS0; 3748c2ecf20Sopenharmony_ci iomd_dma[DMA_S1].base = IOMD_BASE + IOMD_SD1CURA; 3758c2ecf20Sopenharmony_ci iomd_dma[DMA_S1].irq = IRQ_DMAS1; 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci for (i = DMA_0; i <= DMA_S1; i++) { 3788c2ecf20Sopenharmony_ci iomd_dma[i].dma.d_ops = &iomd_dma_ops; 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci ret = isa_dma_add(i, &iomd_dma[i].dma); 3818c2ecf20Sopenharmony_ci if (ret) 3828c2ecf20Sopenharmony_ci printk("IOMDDMA%u: unable to register: %d\n", i, ret); 3838c2ecf20Sopenharmony_ci } 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci ret = isa_dma_add(DMA_VIRTUAL_FLOPPY, &floppy_dma.dma); 3868c2ecf20Sopenharmony_ci if (ret) 3878c2ecf20Sopenharmony_ci printk("IOMDFLOPPY: unable to register: %d\n", ret); 3888c2ecf20Sopenharmony_ci ret = isa_dma_add(DMA_VIRTUAL_SOUND, &sound_dma); 3898c2ecf20Sopenharmony_ci if (ret) 3908c2ecf20Sopenharmony_ci printk("IOMDSOUND: unable to register: %d\n", ret); 3918c2ecf20Sopenharmony_ci return 0; 3928c2ecf20Sopenharmony_ci} 3938c2ecf20Sopenharmony_cicore_initcall(rpc_dma_init); 394