dma-isa.c (5178B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * linux/arch/arm/kernel/dma-isa.c 4 * 5 * Copyright (C) 1999-2000 Russell King 6 * 7 * ISA DMA primitives 8 * Taken from various sources, including: 9 * linux/include/asm/dma.h: Defines for using and allocating dma channels. 10 * Written by Hennus Bergman, 1992. 11 * High DMA channel support & info by Hannu Savolainen and John Boyd, 12 * Nov. 1992. 13 * arch/arm/kernel/dma-ebsa285.c 14 * Copyright (C) 1998 Phil Blundell 15 */ 16#include <linux/ioport.h> 17#include <linux/init.h> 18#include <linux/dma-mapping.h> 19#include <linux/io.h> 20 21#include <asm/dma.h> 22#include <asm/mach/dma.h> 23 24#define ISA_DMA_MASK 0 25#define ISA_DMA_MODE 1 26#define ISA_DMA_CLRFF 2 27#define ISA_DMA_PGHI 3 28#define ISA_DMA_PGLO 4 29#define ISA_DMA_ADDR 5 30#define ISA_DMA_COUNT 6 31 32static unsigned int isa_dma_port[8][7] = { 33 /* MASK MODE CLRFF PAGE_HI PAGE_LO ADDR COUNT */ 34 { 0x0a, 0x0b, 0x0c, 0x487, 0x087, 0x00, 0x01 }, 35 { 0x0a, 0x0b, 0x0c, 0x483, 0x083, 0x02, 0x03 }, 36 { 0x0a, 0x0b, 0x0c, 0x481, 0x081, 0x04, 0x05 }, 37 { 0x0a, 0x0b, 0x0c, 0x482, 0x082, 0x06, 0x07 }, 38 { 0xd4, 0xd6, 0xd8, 0x000, 0x000, 0xc0, 0xc2 }, 39 { 0xd4, 0xd6, 0xd8, 0x48b, 0x08b, 0xc4, 0xc6 }, 40 { 0xd4, 0xd6, 0xd8, 0x489, 0x089, 0xc8, 0xca }, 41 { 0xd4, 0xd6, 0xd8, 0x48a, 0x08a, 0xcc, 0xce } 42}; 43 44static int isa_get_dma_residue(unsigned int chan, dma_t *dma) 45{ 46 unsigned int io_port = isa_dma_port[chan][ISA_DMA_COUNT]; 47 int count; 48 49 count = 1 + inb(io_port); 50 count |= inb(io_port) << 8; 51 52 return chan < 4 ? count : (count << 1); 53} 54 55static struct device isa_dma_dev = { 56 .init_name = "fallback device", 57 .coherent_dma_mask = ~(dma_addr_t)0, 58 .dma_mask = &isa_dma_dev.coherent_dma_mask, 59}; 60 61static void isa_enable_dma(unsigned int chan, dma_t *dma) 62{ 63 if (dma->invalid) { 64 unsigned long address, length; 65 unsigned int mode; 66 enum dma_data_direction direction; 67 68 mode = (chan & 3) | dma->dma_mode; 69 switch (dma->dma_mode & DMA_MODE_MASK) { 70 case DMA_MODE_READ: 71 direction = DMA_FROM_DEVICE; 72 break; 73 74 case DMA_MODE_WRITE: 75 direction = DMA_TO_DEVICE; 76 break; 77 78 case DMA_MODE_CASCADE: 79 direction = DMA_BIDIRECTIONAL; 80 break; 81 82 default: 83 direction = DMA_NONE; 84 break; 85 } 86 87 if (!dma->sg) { 88 /* 89 * Cope with ISA-style drivers which expect cache 90 * coherence. 91 */ 92 dma->sg = &dma->buf; 93 dma->sgcount = 1; 94 dma->buf.length = dma->count; 95 dma->buf.dma_address = dma_map_single(&isa_dma_dev, 96 dma->addr, dma->count, 97 direction); 98 } 99 100 address = dma->buf.dma_address; 101 length = dma->buf.length - 1; 102 103 outb(address >> 16, isa_dma_port[chan][ISA_DMA_PGLO]); 104 outb(address >> 24, isa_dma_port[chan][ISA_DMA_PGHI]); 105 106 if (chan >= 4) { 107 address >>= 1; 108 length >>= 1; 109 } 110 111 outb(0, isa_dma_port[chan][ISA_DMA_CLRFF]); 112 113 outb(address, isa_dma_port[chan][ISA_DMA_ADDR]); 114 outb(address >> 8, isa_dma_port[chan][ISA_DMA_ADDR]); 115 116 outb(length, isa_dma_port[chan][ISA_DMA_COUNT]); 117 outb(length >> 8, isa_dma_port[chan][ISA_DMA_COUNT]); 118 119 outb(mode, isa_dma_port[chan][ISA_DMA_MODE]); 120 dma->invalid = 0; 121 } 122 outb(chan & 3, isa_dma_port[chan][ISA_DMA_MASK]); 123} 124 125static void isa_disable_dma(unsigned int chan, dma_t *dma) 126{ 127 outb(chan | 4, isa_dma_port[chan][ISA_DMA_MASK]); 128} 129 130static struct dma_ops isa_dma_ops = { 131 .type = "ISA", 132 .enable = isa_enable_dma, 133 .disable = isa_disable_dma, 134 .residue = isa_get_dma_residue, 135}; 136 137static struct resource dma_resources[] = { { 138 .name = "dma1", 139 .start = 0x0000, 140 .end = 0x000f 141}, { 142 .name = "dma low page", 143 .start = 0x0080, 144 .end = 0x008f 145}, { 146 .name = "dma2", 147 .start = 0x00c0, 148 .end = 0x00df 149}, { 150 .name = "dma high page", 151 .start = 0x0480, 152 .end = 0x048f 153} }; 154 155static dma_t isa_dma[8]; 156 157/* 158 * ISA DMA always starts at channel 0 159 */ 160void __init isa_init_dma(void) 161{ 162 /* 163 * Try to autodetect presence of an ISA DMA controller. 164 * We do some minimal initialisation, and check that 165 * channel 0's DMA address registers are writeable. 166 */ 167 outb(0xff, 0x0d); 168 outb(0xff, 0xda); 169 170 /* 171 * Write high and low address, and then read them back 172 * in the same order. 173 */ 174 outb(0x55, 0x00); 175 outb(0xaa, 0x00); 176 177 if (inb(0) == 0x55 && inb(0) == 0xaa) { 178 unsigned int chan, i; 179 180 for (chan = 0; chan < 8; chan++) { 181 isa_dma[chan].d_ops = &isa_dma_ops; 182 isa_disable_dma(chan, NULL); 183 } 184 185 outb(0x40, 0x0b); 186 outb(0x41, 0x0b); 187 outb(0x42, 0x0b); 188 outb(0x43, 0x0b); 189 190 outb(0xc0, 0xd6); 191 outb(0x41, 0xd6); 192 outb(0x42, 0xd6); 193 outb(0x43, 0xd6); 194 195 outb(0, 0xd4); 196 197 outb(0x10, 0x08); 198 outb(0x10, 0xd0); 199 200 /* 201 * Is this correct? According to my documentation, it 202 * doesn't appear to be. It should be: 203 * outb(0x3f, 0x40b); outb(0x3f, 0x4d6); 204 */ 205 outb(0x30, 0x40b); 206 outb(0x31, 0x40b); 207 outb(0x32, 0x40b); 208 outb(0x33, 0x40b); 209 outb(0x31, 0x4d6); 210 outb(0x32, 0x4d6); 211 outb(0x33, 0x4d6); 212 213 for (i = 0; i < ARRAY_SIZE(dma_resources); i++) 214 request_resource(&ioport_resource, dma_resources + i); 215 216 for (chan = 0; chan < 8; chan++) { 217 int ret = isa_dma_add(chan, &isa_dma[chan]); 218 if (ret) 219 pr_err("ISADMA%u: unable to register: %d\n", 220 chan, ret); 221 } 222 223 request_dma(DMA_ISA_CASCADE, "cascade"); 224 } 225}