1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * linux/arch/arm/mach-rpc/dma.c 3*1da177e4SLinus Torvalds * 4*1da177e4SLinus Torvalds * Copyright (C) 1998 Russell King 5*1da177e4SLinus Torvalds * 6*1da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 7*1da177e4SLinus Torvalds * it under the terms of the GNU General Public License version 2 as 8*1da177e4SLinus Torvalds * published by the Free Software Foundation. 9*1da177e4SLinus Torvalds * 10*1da177e4SLinus Torvalds * DMA functions specific to RiscPC architecture 11*1da177e4SLinus Torvalds */ 12*1da177e4SLinus Torvalds #include <linux/slab.h> 13*1da177e4SLinus Torvalds #include <linux/mman.h> 14*1da177e4SLinus Torvalds #include <linux/init.h> 15*1da177e4SLinus Torvalds #include <linux/interrupt.h> 16*1da177e4SLinus Torvalds #include <linux/pci.h> 17*1da177e4SLinus Torvalds 18*1da177e4SLinus Torvalds #include <asm/page.h> 19*1da177e4SLinus Torvalds #include <asm/dma.h> 20*1da177e4SLinus Torvalds #include <asm/fiq.h> 21*1da177e4SLinus Torvalds #include <asm/io.h> 22*1da177e4SLinus Torvalds #include <asm/irq.h> 23*1da177e4SLinus Torvalds #include <asm/hardware.h> 24*1da177e4SLinus Torvalds #include <asm/uaccess.h> 25*1da177e4SLinus Torvalds 26*1da177e4SLinus Torvalds #include <asm/mach/dma.h> 27*1da177e4SLinus Torvalds #include <asm/hardware/iomd.h> 28*1da177e4SLinus Torvalds 29*1da177e4SLinus Torvalds #if 0 30*1da177e4SLinus Torvalds typedef enum { 31*1da177e4SLinus Torvalds dma_size_8 = 1, 32*1da177e4SLinus Torvalds dma_size_16 = 2, 33*1da177e4SLinus Torvalds dma_size_32 = 4, 34*1da177e4SLinus Torvalds dma_size_128 = 16 35*1da177e4SLinus Torvalds } dma_size_t; 36*1da177e4SLinus Torvalds #endif 37*1da177e4SLinus Torvalds 38*1da177e4SLinus Torvalds #define TRANSFER_SIZE 2 39*1da177e4SLinus Torvalds 40*1da177e4SLinus Torvalds #define CURA (0) 41*1da177e4SLinus Torvalds #define ENDA (IOMD_IO0ENDA - IOMD_IO0CURA) 42*1da177e4SLinus Torvalds #define CURB (IOMD_IO0CURB - IOMD_IO0CURA) 43*1da177e4SLinus Torvalds #define ENDB (IOMD_IO0ENDB - IOMD_IO0CURA) 44*1da177e4SLinus Torvalds #define CR (IOMD_IO0CR - IOMD_IO0CURA) 45*1da177e4SLinus Torvalds #define ST (IOMD_IO0ST - IOMD_IO0CURA) 46*1da177e4SLinus Torvalds 47*1da177e4SLinus Torvalds static void iomd_get_next_sg(struct scatterlist *sg, dma_t *dma) 48*1da177e4SLinus Torvalds { 49*1da177e4SLinus Torvalds unsigned long end, offset, flags = 0; 50*1da177e4SLinus Torvalds 51*1da177e4SLinus Torvalds if (dma->sg) { 52*1da177e4SLinus Torvalds sg->dma_address = dma->sg->dma_address; 53*1da177e4SLinus Torvalds offset = sg->dma_address & ~PAGE_MASK; 54*1da177e4SLinus Torvalds 55*1da177e4SLinus Torvalds end = offset + dma->sg->length; 56*1da177e4SLinus Torvalds 57*1da177e4SLinus Torvalds if (end > PAGE_SIZE) 58*1da177e4SLinus Torvalds end = PAGE_SIZE; 59*1da177e4SLinus Torvalds 60*1da177e4SLinus Torvalds if (offset + TRANSFER_SIZE >= end) 61*1da177e4SLinus Torvalds flags |= DMA_END_L; 62*1da177e4SLinus Torvalds 63*1da177e4SLinus Torvalds sg->length = end - TRANSFER_SIZE; 64*1da177e4SLinus Torvalds 65*1da177e4SLinus Torvalds dma->sg->length -= end - offset; 66*1da177e4SLinus Torvalds dma->sg->dma_address += end - offset; 67*1da177e4SLinus Torvalds 68*1da177e4SLinus Torvalds if (dma->sg->length == 0) { 69*1da177e4SLinus Torvalds if (dma->sgcount > 1) { 70*1da177e4SLinus Torvalds dma->sg++; 71*1da177e4SLinus Torvalds dma->sgcount--; 72*1da177e4SLinus Torvalds } else { 73*1da177e4SLinus Torvalds dma->sg = NULL; 74*1da177e4SLinus Torvalds flags |= DMA_END_S; 75*1da177e4SLinus Torvalds } 76*1da177e4SLinus Torvalds } 77*1da177e4SLinus Torvalds } else { 78*1da177e4SLinus Torvalds flags = DMA_END_S | DMA_END_L; 79*1da177e4SLinus Torvalds sg->dma_address = 0; 80*1da177e4SLinus Torvalds sg->length = 0; 81*1da177e4SLinus Torvalds } 82*1da177e4SLinus Torvalds 83*1da177e4SLinus Torvalds sg->length |= flags; 84*1da177e4SLinus Torvalds } 85*1da177e4SLinus Torvalds 86*1da177e4SLinus Torvalds static irqreturn_t iomd_dma_handle(int irq, void *dev_id, struct pt_regs *regs) 87*1da177e4SLinus Torvalds { 88*1da177e4SLinus Torvalds dma_t *dma = (dma_t *)dev_id; 89*1da177e4SLinus Torvalds unsigned long base = dma->dma_base; 90*1da177e4SLinus Torvalds 91*1da177e4SLinus Torvalds do { 92*1da177e4SLinus Torvalds unsigned int status; 93*1da177e4SLinus Torvalds 94*1da177e4SLinus Torvalds status = iomd_readb(base + ST); 95*1da177e4SLinus Torvalds if (!(status & DMA_ST_INT)) 96*1da177e4SLinus Torvalds return IRQ_HANDLED; 97*1da177e4SLinus Torvalds 98*1da177e4SLinus Torvalds if ((dma->state ^ status) & DMA_ST_AB) 99*1da177e4SLinus Torvalds iomd_get_next_sg(&dma->cur_sg, dma); 100*1da177e4SLinus Torvalds 101*1da177e4SLinus Torvalds switch (status & (DMA_ST_OFL | DMA_ST_AB)) { 102*1da177e4SLinus Torvalds case DMA_ST_OFL: /* OIA */ 103*1da177e4SLinus Torvalds case DMA_ST_AB: /* .IB */ 104*1da177e4SLinus Torvalds iomd_writel(dma->cur_sg.dma_address, base + CURA); 105*1da177e4SLinus Torvalds iomd_writel(dma->cur_sg.length, base + ENDA); 106*1da177e4SLinus Torvalds dma->state = DMA_ST_AB; 107*1da177e4SLinus Torvalds break; 108*1da177e4SLinus Torvalds 109*1da177e4SLinus Torvalds case DMA_ST_OFL | DMA_ST_AB: /* OIB */ 110*1da177e4SLinus Torvalds case 0: /* .IA */ 111*1da177e4SLinus Torvalds iomd_writel(dma->cur_sg.dma_address, base + CURB); 112*1da177e4SLinus Torvalds iomd_writel(dma->cur_sg.length, base + ENDB); 113*1da177e4SLinus Torvalds dma->state = 0; 114*1da177e4SLinus Torvalds break; 115*1da177e4SLinus Torvalds } 116*1da177e4SLinus Torvalds 117*1da177e4SLinus Torvalds if (status & DMA_ST_OFL && 118*1da177e4SLinus Torvalds dma->cur_sg.length == (DMA_END_S|DMA_END_L)) 119*1da177e4SLinus Torvalds break; 120*1da177e4SLinus Torvalds } while (1); 121*1da177e4SLinus Torvalds 122*1da177e4SLinus Torvalds dma->state = ~DMA_ST_AB; 123*1da177e4SLinus Torvalds disable_irq(irq); 124*1da177e4SLinus Torvalds 125*1da177e4SLinus Torvalds return IRQ_HANDLED; 126*1da177e4SLinus Torvalds } 127*1da177e4SLinus Torvalds 128*1da177e4SLinus Torvalds static int iomd_request_dma(dmach_t channel, dma_t *dma) 129*1da177e4SLinus Torvalds { 130*1da177e4SLinus Torvalds return request_irq(dma->dma_irq, iomd_dma_handle, 131*1da177e4SLinus Torvalds SA_INTERRUPT, dma->device_id, dma); 132*1da177e4SLinus Torvalds } 133*1da177e4SLinus Torvalds 134*1da177e4SLinus Torvalds static void iomd_free_dma(dmach_t channel, dma_t *dma) 135*1da177e4SLinus Torvalds { 136*1da177e4SLinus Torvalds free_irq(dma->dma_irq, dma); 137*1da177e4SLinus Torvalds } 138*1da177e4SLinus Torvalds 139*1da177e4SLinus Torvalds static void iomd_enable_dma(dmach_t channel, dma_t *dma) 140*1da177e4SLinus Torvalds { 141*1da177e4SLinus Torvalds unsigned long dma_base = dma->dma_base; 142*1da177e4SLinus Torvalds unsigned int ctrl = TRANSFER_SIZE | DMA_CR_E; 143*1da177e4SLinus Torvalds 144*1da177e4SLinus Torvalds if (dma->invalid) { 145*1da177e4SLinus Torvalds dma->invalid = 0; 146*1da177e4SLinus Torvalds 147*1da177e4SLinus Torvalds /* 148*1da177e4SLinus Torvalds * Cope with ISA-style drivers which expect cache 149*1da177e4SLinus Torvalds * coherence. 150*1da177e4SLinus Torvalds */ 151*1da177e4SLinus Torvalds if (!dma->using_sg) { 152*1da177e4SLinus Torvalds dma->buf.dma_address = pci_map_single(NULL, 153*1da177e4SLinus Torvalds dma->buf.__address, dma->buf.length, 154*1da177e4SLinus Torvalds dma->dma_mode == DMA_MODE_READ ? 155*1da177e4SLinus Torvalds PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); 156*1da177e4SLinus Torvalds } 157*1da177e4SLinus Torvalds 158*1da177e4SLinus Torvalds iomd_writeb(DMA_CR_C, dma_base + CR); 159*1da177e4SLinus Torvalds dma->state = DMA_ST_AB; 160*1da177e4SLinus Torvalds } 161*1da177e4SLinus Torvalds 162*1da177e4SLinus Torvalds if (dma->dma_mode == DMA_MODE_READ) 163*1da177e4SLinus Torvalds ctrl |= DMA_CR_D; 164*1da177e4SLinus Torvalds 165*1da177e4SLinus Torvalds iomd_writeb(ctrl, dma_base + CR); 166*1da177e4SLinus Torvalds enable_irq(dma->dma_irq); 167*1da177e4SLinus Torvalds } 168*1da177e4SLinus Torvalds 169*1da177e4SLinus Torvalds static void iomd_disable_dma(dmach_t channel, dma_t *dma) 170*1da177e4SLinus Torvalds { 171*1da177e4SLinus Torvalds unsigned long dma_base = dma->dma_base; 172*1da177e4SLinus Torvalds unsigned long flags; 173*1da177e4SLinus Torvalds 174*1da177e4SLinus Torvalds local_irq_save(flags); 175*1da177e4SLinus Torvalds if (dma->state != ~DMA_ST_AB) 176*1da177e4SLinus Torvalds disable_irq(dma->dma_irq); 177*1da177e4SLinus Torvalds iomd_writeb(0, dma_base + CR); 178*1da177e4SLinus Torvalds local_irq_restore(flags); 179*1da177e4SLinus Torvalds } 180*1da177e4SLinus Torvalds 181*1da177e4SLinus Torvalds static int iomd_set_dma_speed(dmach_t channel, dma_t *dma, int cycle) 182*1da177e4SLinus Torvalds { 183*1da177e4SLinus Torvalds int tcr, speed; 184*1da177e4SLinus Torvalds 185*1da177e4SLinus Torvalds if (cycle < 188) 186*1da177e4SLinus Torvalds speed = 3; 187*1da177e4SLinus Torvalds else if (cycle <= 250) 188*1da177e4SLinus Torvalds speed = 2; 189*1da177e4SLinus Torvalds else if (cycle < 438) 190*1da177e4SLinus Torvalds speed = 1; 191*1da177e4SLinus Torvalds else 192*1da177e4SLinus Torvalds speed = 0; 193*1da177e4SLinus Torvalds 194*1da177e4SLinus Torvalds tcr = iomd_readb(IOMD_DMATCR); 195*1da177e4SLinus Torvalds speed &= 3; 196*1da177e4SLinus Torvalds 197*1da177e4SLinus Torvalds switch (channel) { 198*1da177e4SLinus Torvalds case DMA_0: 199*1da177e4SLinus Torvalds tcr = (tcr & ~0x03) | speed; 200*1da177e4SLinus Torvalds break; 201*1da177e4SLinus Torvalds 202*1da177e4SLinus Torvalds case DMA_1: 203*1da177e4SLinus Torvalds tcr = (tcr & ~0x0c) | (speed << 2); 204*1da177e4SLinus Torvalds break; 205*1da177e4SLinus Torvalds 206*1da177e4SLinus Torvalds case DMA_2: 207*1da177e4SLinus Torvalds tcr = (tcr & ~0x30) | (speed << 4); 208*1da177e4SLinus Torvalds break; 209*1da177e4SLinus Torvalds 210*1da177e4SLinus Torvalds case DMA_3: 211*1da177e4SLinus Torvalds tcr = (tcr & ~0xc0) | (speed << 6); 212*1da177e4SLinus Torvalds break; 213*1da177e4SLinus Torvalds 214*1da177e4SLinus Torvalds default: 215*1da177e4SLinus Torvalds break; 216*1da177e4SLinus Torvalds } 217*1da177e4SLinus Torvalds 218*1da177e4SLinus Torvalds iomd_writeb(tcr, IOMD_DMATCR); 219*1da177e4SLinus Torvalds 220*1da177e4SLinus Torvalds return speed; 221*1da177e4SLinus Torvalds } 222*1da177e4SLinus Torvalds 223*1da177e4SLinus Torvalds static struct dma_ops iomd_dma_ops = { 224*1da177e4SLinus Torvalds .type = "IOMD", 225*1da177e4SLinus Torvalds .request = iomd_request_dma, 226*1da177e4SLinus Torvalds .free = iomd_free_dma, 227*1da177e4SLinus Torvalds .enable = iomd_enable_dma, 228*1da177e4SLinus Torvalds .disable = iomd_disable_dma, 229*1da177e4SLinus Torvalds .setspeed = iomd_set_dma_speed, 230*1da177e4SLinus Torvalds }; 231*1da177e4SLinus Torvalds 232*1da177e4SLinus Torvalds static struct fiq_handler fh = { 233*1da177e4SLinus Torvalds .name = "floppydma" 234*1da177e4SLinus Torvalds }; 235*1da177e4SLinus Torvalds 236*1da177e4SLinus Torvalds static void floppy_enable_dma(dmach_t channel, dma_t *dma) 237*1da177e4SLinus Torvalds { 238*1da177e4SLinus Torvalds void *fiqhandler_start; 239*1da177e4SLinus Torvalds unsigned int fiqhandler_length; 240*1da177e4SLinus Torvalds struct pt_regs regs; 241*1da177e4SLinus Torvalds 242*1da177e4SLinus Torvalds if (dma->using_sg) 243*1da177e4SLinus Torvalds BUG(); 244*1da177e4SLinus Torvalds 245*1da177e4SLinus Torvalds if (dma->dma_mode == DMA_MODE_READ) { 246*1da177e4SLinus Torvalds extern unsigned char floppy_fiqin_start, floppy_fiqin_end; 247*1da177e4SLinus Torvalds fiqhandler_start = &floppy_fiqin_start; 248*1da177e4SLinus Torvalds fiqhandler_length = &floppy_fiqin_end - &floppy_fiqin_start; 249*1da177e4SLinus Torvalds } else { 250*1da177e4SLinus Torvalds extern unsigned char floppy_fiqout_start, floppy_fiqout_end; 251*1da177e4SLinus Torvalds fiqhandler_start = &floppy_fiqout_start; 252*1da177e4SLinus Torvalds fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start; 253*1da177e4SLinus Torvalds } 254*1da177e4SLinus Torvalds 255*1da177e4SLinus Torvalds regs.ARM_r9 = dma->buf.length; 256*1da177e4SLinus Torvalds regs.ARM_r10 = (unsigned long)dma->buf.__address; 257*1da177e4SLinus Torvalds regs.ARM_fp = (unsigned long)FLOPPYDMA_BASE; 258*1da177e4SLinus Torvalds 259*1da177e4SLinus Torvalds if (claim_fiq(&fh)) { 260*1da177e4SLinus Torvalds printk("floppydma: couldn't claim FIQ.\n"); 261*1da177e4SLinus Torvalds return; 262*1da177e4SLinus Torvalds } 263*1da177e4SLinus Torvalds 264*1da177e4SLinus Torvalds set_fiq_handler(fiqhandler_start, fiqhandler_length); 265*1da177e4SLinus Torvalds set_fiq_regs(®s); 266*1da177e4SLinus Torvalds enable_fiq(dma->dma_irq); 267*1da177e4SLinus Torvalds } 268*1da177e4SLinus Torvalds 269*1da177e4SLinus Torvalds static void floppy_disable_dma(dmach_t channel, dma_t *dma) 270*1da177e4SLinus Torvalds { 271*1da177e4SLinus Torvalds disable_fiq(dma->dma_irq); 272*1da177e4SLinus Torvalds release_fiq(&fh); 273*1da177e4SLinus Torvalds } 274*1da177e4SLinus Torvalds 275*1da177e4SLinus Torvalds static int floppy_get_residue(dmach_t channel, dma_t *dma) 276*1da177e4SLinus Torvalds { 277*1da177e4SLinus Torvalds struct pt_regs regs; 278*1da177e4SLinus Torvalds get_fiq_regs(®s); 279*1da177e4SLinus Torvalds return regs.ARM_r9; 280*1da177e4SLinus Torvalds } 281*1da177e4SLinus Torvalds 282*1da177e4SLinus Torvalds static struct dma_ops floppy_dma_ops = { 283*1da177e4SLinus Torvalds .type = "FIQDMA", 284*1da177e4SLinus Torvalds .enable = floppy_enable_dma, 285*1da177e4SLinus Torvalds .disable = floppy_disable_dma, 286*1da177e4SLinus Torvalds .residue = floppy_get_residue, 287*1da177e4SLinus Torvalds }; 288*1da177e4SLinus Torvalds 289*1da177e4SLinus Torvalds /* 290*1da177e4SLinus Torvalds * This is virtual DMA - we don't need anything here. 291*1da177e4SLinus Torvalds */ 292*1da177e4SLinus Torvalds static void sound_enable_disable_dma(dmach_t channel, dma_t *dma) 293*1da177e4SLinus Torvalds { 294*1da177e4SLinus Torvalds } 295*1da177e4SLinus Torvalds 296*1da177e4SLinus Torvalds static struct dma_ops sound_dma_ops = { 297*1da177e4SLinus Torvalds .type = "VIRTUAL", 298*1da177e4SLinus Torvalds .enable = sound_enable_disable_dma, 299*1da177e4SLinus Torvalds .disable = sound_enable_disable_dma, 300*1da177e4SLinus Torvalds }; 301*1da177e4SLinus Torvalds 302*1da177e4SLinus Torvalds void __init arch_dma_init(dma_t *dma) 303*1da177e4SLinus Torvalds { 304*1da177e4SLinus Torvalds iomd_writeb(0, IOMD_IO0CR); 305*1da177e4SLinus Torvalds iomd_writeb(0, IOMD_IO1CR); 306*1da177e4SLinus Torvalds iomd_writeb(0, IOMD_IO2CR); 307*1da177e4SLinus Torvalds iomd_writeb(0, IOMD_IO3CR); 308*1da177e4SLinus Torvalds 309*1da177e4SLinus Torvalds iomd_writeb(0xa0, IOMD_DMATCR); 310*1da177e4SLinus Torvalds 311*1da177e4SLinus Torvalds dma[DMA_0].dma_base = IOMD_IO0CURA; 312*1da177e4SLinus Torvalds dma[DMA_0].dma_irq = IRQ_DMA0; 313*1da177e4SLinus Torvalds dma[DMA_0].d_ops = &iomd_dma_ops; 314*1da177e4SLinus Torvalds dma[DMA_1].dma_base = IOMD_IO1CURA; 315*1da177e4SLinus Torvalds dma[DMA_1].dma_irq = IRQ_DMA1; 316*1da177e4SLinus Torvalds dma[DMA_1].d_ops = &iomd_dma_ops; 317*1da177e4SLinus Torvalds dma[DMA_2].dma_base = IOMD_IO2CURA; 318*1da177e4SLinus Torvalds dma[DMA_2].dma_irq = IRQ_DMA2; 319*1da177e4SLinus Torvalds dma[DMA_2].d_ops = &iomd_dma_ops; 320*1da177e4SLinus Torvalds dma[DMA_3].dma_base = IOMD_IO3CURA; 321*1da177e4SLinus Torvalds dma[DMA_3].dma_irq = IRQ_DMA3; 322*1da177e4SLinus Torvalds dma[DMA_3].d_ops = &iomd_dma_ops; 323*1da177e4SLinus Torvalds dma[DMA_S0].dma_base = IOMD_SD0CURA; 324*1da177e4SLinus Torvalds dma[DMA_S0].dma_irq = IRQ_DMAS0; 325*1da177e4SLinus Torvalds dma[DMA_S0].d_ops = &iomd_dma_ops; 326*1da177e4SLinus Torvalds dma[DMA_S1].dma_base = IOMD_SD1CURA; 327*1da177e4SLinus Torvalds dma[DMA_S1].dma_irq = IRQ_DMAS1; 328*1da177e4SLinus Torvalds dma[DMA_S1].d_ops = &iomd_dma_ops; 329*1da177e4SLinus Torvalds dma[DMA_VIRTUAL_FLOPPY].dma_irq = FIQ_FLOPPYDATA; 330*1da177e4SLinus Torvalds dma[DMA_VIRTUAL_FLOPPY].d_ops = &floppy_dma_ops; 331*1da177e4SLinus Torvalds dma[DMA_VIRTUAL_SOUND].d_ops = &sound_dma_ops; 332*1da177e4SLinus Torvalds 333*1da177e4SLinus Torvalds /* 334*1da177e4SLinus Torvalds * Setup DMA channels 2,3 to be for podules 335*1da177e4SLinus Torvalds * and channels 0,1 for internal devices 336*1da177e4SLinus Torvalds */ 337*1da177e4SLinus Torvalds iomd_writeb(DMA_EXT_IO3|DMA_EXT_IO2, IOMD_DMAEXT); 338*1da177e4SLinus Torvalds } 339