hc
2024-01-04 1543e317f1da31b75942316931e8f491a8920811
kernel/arch/arm/mach-rpc/dma.c
....@@ -1,11 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * linux/arch/arm/mach-rpc/dma.c
34 *
45 * Copyright (C) 1998 Russell King
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License version 2 as
8
- * published by the Free Software Foundation.
96 *
107 * DMA functions specific to RiscPC architecture
118 */
....@@ -27,10 +24,11 @@
2724
2825 struct iomd_dma {
2926 struct dma_struct dma;
30
- unsigned int state;
31
- unsigned long base; /* Controller base address */
27
+ void __iomem *base; /* Controller base address */
3228 int irq; /* Controller IRQ */
33
- struct scatterlist cur_sg; /* Current controller buffer */
29
+ unsigned int state;
30
+ dma_addr_t cur_addr;
31
+ unsigned int cur_len;
3432 dma_addr_t dma_addr;
3533 unsigned int dma_len;
3634 };
....@@ -53,13 +51,13 @@
5351 #define CR (IOMD_IO0CR - IOMD_IO0CURA)
5452 #define ST (IOMD_IO0ST - IOMD_IO0CURA)
5553
56
-static void iomd_get_next_sg(struct scatterlist *sg, struct iomd_dma *idma)
54
+static void iomd_get_next_sg(struct iomd_dma *idma)
5755 {
5856 unsigned long end, offset, flags = 0;
5957
6058 if (idma->dma.sg) {
61
- sg->dma_address = idma->dma_addr;
62
- offset = sg->dma_address & ~PAGE_MASK;
59
+ idma->cur_addr = idma->dma_addr;
60
+ offset = idma->cur_addr & ~PAGE_MASK;
6361
6462 end = offset + idma->dma_len;
6563
....@@ -69,7 +67,7 @@
6967 if (offset + TRANSFER_SIZE >= end)
7068 flags |= DMA_END_L;
7169
72
- sg->length = end - TRANSFER_SIZE;
70
+ idma->cur_len = end - TRANSFER_SIZE;
7371
7472 idma->dma_len -= end - offset;
7573 idma->dma_addr += end - offset;
....@@ -87,52 +85,49 @@
8785 }
8886 } else {
8987 flags = DMA_END_S | DMA_END_L;
90
- sg->dma_address = 0;
91
- sg->length = 0;
88
+ idma->cur_addr = 0;
89
+ idma->cur_len = 0;
9290 }
9391
94
- sg->length |= flags;
92
+ idma->cur_len |= flags;
9593 }
9694
9795 static irqreturn_t iomd_dma_handle(int irq, void *dev_id)
9896 {
9997 struct iomd_dma *idma = dev_id;
100
- unsigned long base = idma->base;
98
+ void __iomem *base = idma->base;
99
+ unsigned int state = idma->state;
100
+ unsigned int status, cur, end;
101101
102102 do {
103
- unsigned int status;
104
-
105
- status = iomd_readb(base + ST);
103
+ status = readb(base + ST);
106104 if (!(status & DMA_ST_INT))
107
- return IRQ_HANDLED;
105
+ goto out;
108106
109
- if ((idma->state ^ status) & DMA_ST_AB)
110
- iomd_get_next_sg(&idma->cur_sg, idma);
107
+ if ((state ^ status) & DMA_ST_AB)
108
+ iomd_get_next_sg(idma);
111109
112
- switch (status & (DMA_ST_OFL | DMA_ST_AB)) {
113
- case DMA_ST_OFL: /* OIA */
114
- case DMA_ST_AB: /* .IB */
115
- iomd_writel(idma->cur_sg.dma_address, base + CURA);
116
- iomd_writel(idma->cur_sg.length, base + ENDA);
117
- idma->state = DMA_ST_AB;
118
- break;
119
-
120
- case DMA_ST_OFL | DMA_ST_AB: /* OIB */
121
- case 0: /* .IA */
122
- iomd_writel(idma->cur_sg.dma_address, base + CURB);
123
- iomd_writel(idma->cur_sg.length, base + ENDB);
124
- idma->state = 0;
125
- break;
110
+ // This efficiently implements state = OFL != AB ? AB : 0
111
+ state = ((status >> 2) ^ status) & DMA_ST_AB;
112
+ if (state) {
113
+ cur = CURA;
114
+ end = ENDA;
115
+ } else {
116
+ cur = CURB;
117
+ end = ENDB;
126118 }
119
+ writel(idma->cur_addr, base + cur);
120
+ writel(idma->cur_len, base + end);
127121
128122 if (status & DMA_ST_OFL &&
129
- idma->cur_sg.length == (DMA_END_S|DMA_END_L))
123
+ idma->cur_len == (DMA_END_S|DMA_END_L))
130124 break;
131125 } while (1);
132126
133
- idma->state = ~DMA_ST_AB;
127
+ state = ~DMA_ST_AB;
134128 disable_irq_nosync(irq);
135
-
129
+out:
130
+ idma->state = state;
136131 return IRQ_HANDLED;
137132 }
138133
....@@ -151,10 +146,16 @@
151146 free_irq(idma->irq, idma);
152147 }
153148
149
+static struct device isa_dma_dev = {
150
+ .init_name = "fallback device",
151
+ .coherent_dma_mask = ~(dma_addr_t)0,
152
+ .dma_mask = &isa_dma_dev.coherent_dma_mask,
153
+};
154
+
154155 static void iomd_enable_dma(unsigned int chan, dma_t *dma)
155156 {
156157 struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma);
157
- unsigned long dma_base = idma->base;
158
+ void __iomem *base = idma->base;
158159 unsigned int ctrl = TRANSFER_SIZE | DMA_CR_E;
159160
160161 if (idma->dma.invalid) {
....@@ -168,7 +169,7 @@
168169 idma->dma.sg = &idma->dma.buf;
169170 idma->dma.sgcount = 1;
170171 idma->dma.buf.length = idma->dma.count;
171
- idma->dma.buf.dma_address = dma_map_single(NULL,
172
+ idma->dma.buf.dma_address = dma_map_single(&isa_dma_dev,
172173 idma->dma.addr, idma->dma.count,
173174 idma->dma.dma_mode == DMA_MODE_READ ?
174175 DMA_FROM_DEVICE : DMA_TO_DEVICE);
....@@ -177,27 +178,27 @@
177178 idma->dma_addr = idma->dma.sg->dma_address;
178179 idma->dma_len = idma->dma.sg->length;
179180
180
- iomd_writeb(DMA_CR_C, dma_base + CR);
181
+ writeb(DMA_CR_C, base + CR);
181182 idma->state = DMA_ST_AB;
182183 }
183184
184185 if (idma->dma.dma_mode == DMA_MODE_READ)
185186 ctrl |= DMA_CR_D;
186187
187
- iomd_writeb(ctrl, dma_base + CR);
188
+ writeb(ctrl, base + CR);
188189 enable_irq(idma->irq);
189190 }
190191
191192 static void iomd_disable_dma(unsigned int chan, dma_t *dma)
192193 {
193194 struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma);
194
- unsigned long dma_base = idma->base;
195
+ void __iomem *base = idma->base;
195196 unsigned long flags;
196197
197198 local_irq_save(flags);
198199 if (idma->state != ~DMA_ST_AB)
199200 disable_irq(idma->irq);
200
- iomd_writeb(0, dma_base + CR);
201
+ writeb(0, base + CR);
201202 local_irq_restore(flags);
202203 }
203204
....@@ -360,17 +361,17 @@
360361 */
361362 iomd_writeb(DMA_EXT_IO3|DMA_EXT_IO2, IOMD_DMAEXT);
362363
363
- iomd_dma[DMA_0].base = IOMD_IO0CURA;
364
+ iomd_dma[DMA_0].base = IOMD_BASE + IOMD_IO0CURA;
364365 iomd_dma[DMA_0].irq = IRQ_DMA0;
365
- iomd_dma[DMA_1].base = IOMD_IO1CURA;
366
+ iomd_dma[DMA_1].base = IOMD_BASE + IOMD_IO1CURA;
366367 iomd_dma[DMA_1].irq = IRQ_DMA1;
367
- iomd_dma[DMA_2].base = IOMD_IO2CURA;
368
+ iomd_dma[DMA_2].base = IOMD_BASE + IOMD_IO2CURA;
368369 iomd_dma[DMA_2].irq = IRQ_DMA2;
369
- iomd_dma[DMA_3].base = IOMD_IO3CURA;
370
+ iomd_dma[DMA_3].base = IOMD_BASE + IOMD_IO3CURA;
370371 iomd_dma[DMA_3].irq = IRQ_DMA3;
371
- iomd_dma[DMA_S0].base = IOMD_SD0CURA;
372
+ iomd_dma[DMA_S0].base = IOMD_BASE + IOMD_SD0CURA;
372373 iomd_dma[DMA_S0].irq = IRQ_DMAS0;
373
- iomd_dma[DMA_S1].base = IOMD_SD1CURA;
374
+ iomd_dma[DMA_S1].base = IOMD_BASE + IOMD_SD1CURA;
374375 iomd_dma[DMA_S1].irq = IRQ_DMAS1;
375376
376377 for (i = DMA_0; i <= DMA_S1; i++) {