1 /* 2 * DMA support for the JZ4730. 3 * 4 * Copyright (C) 2021, 2023, 2024 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 #pragma once 23 24 #include <l4/sys/types.h> 25 #include <stdint.h> 26 27 28 29 /* Enumerated types for various transfer parameters. */ 30 31 enum Dma_jz4730_request_type 32 { 33 Dma_request_external = 0, 34 Dma_request_pcmcia_out = 4, 35 Dma_request_pcmcia_in = 5, 36 Dma_request_auto = 8, 37 Dma_request_des_out = 10, 38 Dma_request_des_in = 11, 39 Dma_request_uart3_out = 14, 40 Dma_request_uart3_in = 15, 41 Dma_request_uart2_out = 16, 42 Dma_request_uart2_in = 17, 43 Dma_request_uart1_out = 18, 44 Dma_request_uart1_in = 19, 45 Dma_request_uart0_out = 20, 46 Dma_request_uart0_in = 21, 47 Dma_request_ssi_out = 22, 48 Dma_request_ssi_in = 23, 49 Dma_request_aic_out = 24, 50 Dma_request_aic_in = 25, 51 Dma_request_msc_out = 26, 52 Dma_request_msc_in = 27, 53 Dma_request_ost2_underflow = 28, 54 }; 55 56 enum Dma_jz4730_ext_level 57 { 58 Dma_ext_active_high = 0, 59 Dma_ext_active_low = 1, 60 }; 61 62 enum Dma_jz4730_ext_output_mode_cycle 63 { 64 Dma_ext_output_mode_read_cycle = 0, 65 Dma_ext_output_mode_write_cycle = 1, 66 }; 67 68 enum Dma_jz4730_ext_req_detect_mode 69 { 70 Dma_ext_req_detect_mode_low_level = 0, 71 Dma_ext_req_detect_mode_falling_edge = 1, 72 Dma_ext_req_detect_mode_high_level = 2, 73 Dma_ext_req_detect_mode_rising_edge = 3, 74 }; 75 76 77 78 #ifdef __cplusplus 79 80 #include <l4/devices/dma-generic.h> 81 #include <l4/devices/hw_mmio_register_block.h> 82 83 // Forward declaration. 84 85 class Dma_jz4730_chip; 86 87 88 89 // DMA channel. 90 91 class Dma_jz4730_channel : public Dma_channel 92 { 93 private: 94 Hw::Register_block<32> _regs; 95 Dma_chip *_chip; 96 uint8_t _channel; 97 l4_cap_idx_t _irq = L4_INVALID_CAP; 98 99 // External transfer properties with defaults. 100 101 enum Dma_jz4730_ext_level _ext_output_polarity = Dma_ext_active_high; 102 enum Dma_jz4730_ext_level _ext_end_of_process_mode = Dma_ext_active_high; 103 enum Dma_jz4730_ext_output_mode_cycle _ext_output_mode_cycle = Dma_ext_output_mode_read_cycle; 104 enum Dma_jz4730_ext_req_detect_mode _ext_req_detect_mode = Dma_ext_req_detect_mode_high_level; 105 106 public: 107 Dma_jz4730_channel(Dma_chip *chip, uint8_t channel, l4_addr_t start, l4_cap_idx_t irq); 108 109 unsigned int transfer(uint32_t source, uint32_t destination, 110 unsigned int count, 111 bool source_increment, bool destination_increment, 112 uint8_t source_width, uint8_t destination_width, 113 uint8_t transfer_unit_size, 114 int type=Dma_request_auto, 115 l4_addr_t desc_vaddr = 0, 116 l4re_dma_space_dma_addr_t desc_paddr = 0); 117 118 unsigned int wait(); 119 120 // External transfer property configuration. 121 122 void set_output_polarity(enum Dma_jz4730_ext_level polarity) 123 { _ext_output_polarity = polarity; } 124 125 void set_end_of_process_mode(enum Dma_jz4730_ext_level mode) 126 { _ext_end_of_process_mode = mode; } 127 128 void set_output_mode_cycle(enum Dma_jz4730_ext_output_mode_cycle cycle) 129 { _ext_output_mode_cycle = cycle; } 130 131 void set_req_detect_mode(enum Dma_jz4730_ext_req_detect_mode mode) 132 { _ext_req_detect_mode = mode; } 133 134 protected: 135 // Transfer property configuration. 136 137 uint32_t encode_external_transfer(enum Dma_jz4730_request_type type); 138 139 uint32_t encode_req_detect_int_length(uint8_t units); 140 141 uint32_t encode_source_port_width(uint8_t width); 142 143 uint32_t encode_destination_port_width(uint8_t width); 144 145 uint32_t encode_transfer_unit_size(uint8_t size); 146 147 // Transaction control. 148 149 void ack_irq(); 150 151 void clear_errors(); 152 153 bool completed(); 154 155 bool error(); 156 157 bool halted(); 158 159 bool wait_for_irq(); 160 161 bool wait_for_irq(unsigned int timeout); 162 }; 163 164 // DMA device control. 165 166 class Dma_jz4730_chip : public Dma_chip 167 { 168 private: 169 Hw::Register_block<32> _regs; 170 l4_addr_t _start, _end; 171 Cpm_chip *_cpm; 172 173 public: 174 Dma_jz4730_chip(l4_addr_t start, l4_addr_t end, Cpm_chip *cpm); 175 176 void disable(); 177 178 void enable(); 179 180 Dma_channel *get_channel(uint8_t channel, l4_cap_idx_t irq = L4_INVALID_CAP); 181 182 bool have_interrupt(uint8_t channel); 183 }; 184 185 Dma_chip *jz4730_dma_chip(l4_addr_t start, l4_addr_t end, Cpm_chip *cpm); 186 187 #endif /* __cplusplus */ 188 189 190 191 /* C language interface. */ 192 193 EXTERN_C_BEGIN 194 195 void *jz4730_dma_init(l4_addr_t start, l4_addr_t end, void *cpm); 196 197 void jz4730_dma_disable(void *dma_chip); 198 199 void jz4730_dma_enable(void *dma_chip); 200 201 void *jz4730_dma_get_channel(void *dma, uint8_t channel, l4_cap_idx_t irq); 202 203 void jz4730_dma_set_output_polarity(void *dma_channel, enum Dma_jz4730_ext_level polarity); 204 205 void jz4730_dma_set_end_of_process_mode(void *dma_channel, enum Dma_jz4730_ext_level mode); 206 207 void jz4730_dma_set_output_mode_cycle(void *dma_channel, enum Dma_jz4730_ext_output_mode_cycle cycle); 208 209 void jz4730_dma_set_req_detect_mode(void *dma_channel, enum Dma_jz4730_ext_req_detect_mode mode); 210 211 unsigned int jz4730_dma_transfer(void *dma_channel, 212 uint32_t source, uint32_t destination, 213 unsigned int count, 214 int source_increment, int destination_increment, 215 uint8_t source_width, uint8_t destination_width, 216 uint8_t transfer_unit_size, 217 enum Dma_jz4730_request_type type); 218 219 unsigned int jz4730_dma_wait(void *dma_channel); 220 221 EXTERN_C_END