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