|
1 /* |
|
2 * On-chip DMA controller framework. |
|
3 * |
|
4 * Copyright (C) 2008 Nokia Corporation |
|
5 * Written by Andrzej Zaborowski <andrew@openedhand.com> |
|
6 * |
|
7 * This program is free software; you can redistribute it and/or |
|
8 * modify it under the terms of the GNU General Public License as |
|
9 * published by the Free Software Foundation; either version 2 or |
|
10 * (at your option) version 3 of the License. |
|
11 * |
|
12 * This program is distributed in the hope that it will be useful, |
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
15 * GNU General Public License for more details. |
|
16 * |
|
17 * You should have received a copy of the GNU General Public License |
|
18 * along with this program; if not, write to the Free Software |
|
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
|
20 * MA 02111-1307 USA |
|
21 */ |
|
22 |
|
23 struct soc_dma_s; |
|
24 struct soc_dma_ch_s; |
|
25 typedef void (*soc_dma_io_t)(void *opaque, uint8_t *buf, int len); |
|
26 typedef void (*soc_dma_transfer_t)(struct soc_dma_ch_s *ch); |
|
27 |
|
28 enum soc_dma_port_type { |
|
29 soc_dma_port_mem, |
|
30 soc_dma_port_fifo, |
|
31 soc_dma_port_other, |
|
32 }; |
|
33 |
|
34 enum soc_dma_access_type { |
|
35 soc_dma_access_const, |
|
36 soc_dma_access_linear, |
|
37 soc_dma_access_other, |
|
38 }; |
|
39 |
|
40 struct soc_dma_ch_s { |
|
41 /* Private */ |
|
42 struct soc_dma_s *dma; |
|
43 int num; |
|
44 QEMUTimer *timer; |
|
45 |
|
46 /* Set by soc_dma.c */ |
|
47 int enable; |
|
48 int update; |
|
49 |
|
50 /* This should be set by dma->setup_fn(). */ |
|
51 int bytes; |
|
52 /* Initialised by the DMA module, call soc_dma_ch_update after writing. */ |
|
53 enum soc_dma_access_type type[2]; |
|
54 target_phys_addr_t vaddr[2]; /* Updated by .transfer_fn(). */ |
|
55 /* Private */ |
|
56 void *paddr[2]; |
|
57 soc_dma_io_t io_fn[2]; |
|
58 void *io_opaque[2]; |
|
59 |
|
60 int running; |
|
61 soc_dma_transfer_t transfer_fn; |
|
62 |
|
63 /* Set and used by the DMA module. */ |
|
64 void *opaque; |
|
65 }; |
|
66 |
|
67 struct soc_dma_s { |
|
68 /* Following fields are set by the SoC DMA module and can be used |
|
69 * by anybody. */ |
|
70 uint64_t drqbmp; /* Is zeroed by soc_dma_reset() */ |
|
71 qemu_irq *drq; |
|
72 void *opaque; |
|
73 int64_t freq; |
|
74 soc_dma_transfer_t transfer_fn; |
|
75 soc_dma_transfer_t setup_fn; |
|
76 /* Set by soc_dma_init() for use by the DMA module. */ |
|
77 struct soc_dma_ch_s *ch; |
|
78 }; |
|
79 |
|
80 /* Call to activate or stop a DMA channel. */ |
|
81 void soc_dma_set_request(struct soc_dma_ch_s *ch, int level); |
|
82 /* Call after every write to one of the following fields and before |
|
83 * calling soc_dma_set_request(ch, 1): |
|
84 * ch->type[0...1], |
|
85 * ch->vaddr[0...1], |
|
86 * ch->paddr[0...1], |
|
87 * or after a soc_dma_port_add_fifo() or soc_dma_port_add_mem(). */ |
|
88 void soc_dma_ch_update(struct soc_dma_ch_s *ch); |
|
89 |
|
90 /* The SoC should call this when the DMA module is being reset. */ |
|
91 void soc_dma_reset(struct soc_dma_s *s); |
|
92 struct soc_dma_s *soc_dma_init(int n); |
|
93 |
|
94 void soc_dma_port_add_fifo(struct soc_dma_s *dma, target_phys_addr_t virt_base, |
|
95 soc_dma_io_t fn, void *opaque, int out); |
|
96 void soc_dma_port_add_mem(struct soc_dma_s *dma, uint8_t *phys_base, |
|
97 target_phys_addr_t virt_base, size_t size); |
|
98 |
|
99 static inline void soc_dma_port_add_fifo_in(struct soc_dma_s *dma, |
|
100 target_phys_addr_t virt_base, soc_dma_io_t fn, void *opaque) |
|
101 { |
|
102 return soc_dma_port_add_fifo(dma, virt_base, fn, opaque, 0); |
|
103 } |
|
104 |
|
105 static inline void soc_dma_port_add_fifo_out(struct soc_dma_s *dma, |
|
106 target_phys_addr_t virt_base, soc_dma_io_t fn, void *opaque) |
|
107 { |
|
108 return soc_dma_port_add_fifo(dma, virt_base, fn, opaque, 1); |
|
109 } |
|
110 |
|
111 static inline void soc_dma_port_add_mem_ram(struct soc_dma_s *dma, |
|
112 ram_addr_t offset, target_phys_addr_t virt_base, size_t size) |
|
113 { |
|
114 /* FIXME: This is broken if it spans multiple RAM regions. */ |
|
115 return soc_dma_port_add_mem(dma, host_ram_addr(offset), virt_base, size); |
|
116 } |