1 /* 2 * DMA support for the JZ4730. 3 * 4 * Copyright (C) 2021 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 : unsigned 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_send_empty = 22, 48 Dma_request_ssi_recv_full = 23, 49 Dma_request_aic_send_empty = 24, 50 Dma_request_aic_recv_full = 25, 51 Dma_request_msc_send_empty = 26, 52 Dma_request_msc_recv_full = 27, 53 Dma_request_ost2_underflow = 28, 54 }; 55 56 enum Dma_jz4730_ext_level : unsigned 57 { 58 Dma_ext_active_high = 0, 59 Dma_ext_active_low = 1, 60 }; 61 62 enum Dma_jz4730_ext_output_mode_cycle : unsigned 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 : unsigned 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 enum Dma_jz4730_trans_unit_size : unsigned 77 { 78 Dma_trans_unit_size_32_bit = 0, 79 Dma_trans_unit_size_8_bit = 1, 80 Dma_trans_unit_size_16_bit = 2, 81 Dma_trans_unit_size_16_byte = 3, 82 Dma_trans_unit_size_32_byte = 4, 83 }; 84 85 86 87 #ifdef __cplusplus 88 89 #include <l4/devices/cpm-jz4730.h> 90 #include <l4/devices/hw_mmio_register_block.h> 91 92 // Forward declaration. 93 94 class Dma_jz4730_chip; 95 96 97 98 // DMA channel. 99 100 class Dma_jz4730_channel 101 { 102 private: 103 Hw::Register_block<32> _regs; 104 Dma_jz4730_chip *_chip; 105 uint8_t _channel; 106 l4_cap_idx_t _irq=L4_INVALID_CAP; 107 108 // External transfer properties with defaults. 109 110 enum Dma_jz4730_ext_level _ext_output_polarity = Dma_ext_active_high; 111 enum Dma_jz4730_ext_level _ext_end_of_process_mode = Dma_ext_active_high; 112 enum Dma_jz4730_ext_output_mode_cycle _ext_output_mode_cycle = Dma_ext_output_mode_read_cycle; 113 enum Dma_jz4730_ext_req_detect_mode _ext_req_detect_mode = Dma_ext_req_detect_mode_high_level; 114 115 public: 116 Dma_jz4730_channel(Dma_jz4730_chip *chip, uint8_t channel, l4_addr_t start, l4_cap_idx_t irq); 117 118 unsigned int transfer(uint32_t source, uint32_t destination, 119 unsigned int count, 120 enum Dma_jz4730_trans_unit_size size, 121 enum Dma_jz4730_request_type type=Dma_request_auto); 122 123 // External transfer property configuration. 124 125 void set_output_polarity(enum Dma_jz4730_ext_level polarity) 126 { _ext_output_polarity = polarity; } 127 128 void set_end_of_process_mode(enum Dma_jz4730_ext_level mode) 129 { _ext_end_of_process_mode = mode; } 130 131 void set_output_mode_cycle(enum Dma_jz4730_ext_output_mode_cycle cycle) 132 { _ext_output_mode_cycle = cycle; } 133 134 void set_req_detect_mode(enum Dma_jz4730_ext_req_detect_mode mode) 135 { _ext_req_detect_mode = mode; } 136 137 protected: 138 // Transfer property configuration. 139 140 uint32_t encode_external_transfer(enum Dma_jz4730_request_type type); 141 142 uint32_t encode_source_address_increment(enum Dma_jz4730_request_type type); 143 144 uint32_t encode_destination_address_increment(enum Dma_jz4730_request_type type); 145 146 uint32_t encode_req_detect_int_length(uint8_t units); 147 148 uint32_t encode_source_port_width(enum Dma_jz4730_request_type type); 149 150 uint32_t encode_destination_port_width(enum Dma_jz4730_request_type type); 151 152 // Transaction control. 153 154 void ack_irq(); 155 156 bool completed(); 157 158 bool error(); 159 160 bool halted(); 161 162 bool wait_for_irq(); 163 164 bool wait_for_irq(unsigned int timeout); 165 }; 166 167 // DMA device control. 168 169 class Dma_jz4730_chip 170 { 171 private: 172 Hw::Register_block<32> _regs; 173 l4_addr_t _start, _end; 174 Cpm_jz4730_chip *_cpm; 175 176 public: 177 Dma_jz4730_chip(l4_addr_t start, l4_addr_t end, Cpm_jz4730_chip *cpm); 178 179 void disable(); 180 181 void enable(); 182 183 Dma_jz4730_channel *get_channel(uint8_t channel, l4_cap_idx_t irq); 184 185 bool have_interrupt(uint8_t channel); 186 }; 187 188 #endif /* __cplusplus */ 189 190 191 192 /* C language interface. */ 193 194 EXTERN_C_BEGIN 195 196 void *jz4730_dma_init(l4_addr_t start, l4_addr_t end, void *cpm); 197 198 void jz4730_dma_disable(void *dma_chip); 199 200 void jz4730_dma_enable(void *dma_chip); 201 202 void *jz4730_dma_get_channel(void *dma, uint8_t channel, l4_cap_idx_t irq); 203 204 void jz4730_dma_set_output_polarity(void *dma_channel, enum Dma_jz4730_ext_level polarity); 205 206 void jz4730_dma_set_end_of_process_mode(void *dma_channel, enum Dma_jz4730_ext_level mode); 207 208 void jz4730_dma_set_output_mode_cycle(void *dma_channel, enum Dma_jz4730_ext_output_mode_cycle cycle); 209 210 void jz4730_dma_set_req_detect_mode(void *dma_channel, enum Dma_jz4730_ext_req_detect_mode mode); 211 212 unsigned int jz4730_dma_transfer(void *dma_channel, uint32_t source, 213 uint32_t destination, unsigned int count, 214 enum Dma_jz4730_trans_unit_size size, 215 enum Dma_jz4730_request_type type); 216 217 EXTERN_C_END