paul@214 | 1 | /* |
paul@214 | 2 | * DMA support for the JZ4780. |
paul@214 | 3 | * |
paul@214 | 4 | * Copyright (C) 2021, 2023 Paul Boddie <paul@boddie.org.uk> |
paul@214 | 5 | * |
paul@214 | 6 | * This program is free software; you can redistribute it and/or |
paul@214 | 7 | * modify it under the terms of the GNU General Public License as |
paul@214 | 8 | * published by the Free Software Foundation; either version 2 of |
paul@214 | 9 | * the License, or (at your option) any later version. |
paul@214 | 10 | * |
paul@214 | 11 | * This program is distributed in the hope that it will be useful, |
paul@214 | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
paul@214 | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
paul@214 | 14 | * GNU General Public License for more details. |
paul@214 | 15 | * |
paul@214 | 16 | * You should have received a copy of the GNU General Public License |
paul@214 | 17 | * along with this program; if not, write to the Free Software |
paul@214 | 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, |
paul@214 | 19 | * Boston, MA 02110-1301, USA |
paul@214 | 20 | */ |
paul@214 | 21 | |
paul@214 | 22 | #pragma once |
paul@214 | 23 | |
paul@214 | 24 | #include <l4/sys/types.h> |
paul@214 | 25 | #include <stdint.h> |
paul@214 | 26 | |
paul@214 | 27 | |
paul@214 | 28 | |
paul@214 | 29 | /* Enumerated types for various transfer parameters. */ |
paul@214 | 30 | |
paul@214 | 31 | enum Dma_jz4780_request_type |
paul@214 | 32 | { |
paul@214 | 33 | Dma_request_i2s1_out = 4, |
paul@214 | 34 | Dma_request_i2s1_in = 5, |
paul@214 | 35 | Dma_request_i2s0_out = 6, |
paul@214 | 36 | Dma_request_i2s0_in = 7, |
paul@214 | 37 | Dma_request_auto = 8, |
paul@214 | 38 | Dma_request_sadc_in = 9, |
paul@214 | 39 | Dma_request_uart4_out = 12, |
paul@214 | 40 | Dma_request_uart4_in = 13, |
paul@214 | 41 | Dma_request_uart3_out = 14, |
paul@214 | 42 | Dma_request_uart3_in = 15, |
paul@214 | 43 | Dma_request_uart2_out = 16, |
paul@214 | 44 | Dma_request_uart2_in = 17, |
paul@214 | 45 | Dma_request_uart1_out = 18, |
paul@214 | 46 | Dma_request_uart1_in = 19, |
paul@214 | 47 | Dma_request_uart0_out = 20, |
paul@214 | 48 | Dma_request_uart0_in = 21, |
paul@214 | 49 | Dma_request_ssi0_out = 22, |
paul@214 | 50 | Dma_request_ssi0_in = 23, |
paul@214 | 51 | Dma_request_ssi1_out = 24, |
paul@214 | 52 | Dma_request_ssi1_in = 25, |
paul@214 | 53 | Dma_request_msc0_out = 26, |
paul@214 | 54 | Dma_request_msc0_in = 27, |
paul@214 | 55 | Dma_request_msc1_out = 28, |
paul@214 | 56 | Dma_request_msc1_in = 29, |
paul@214 | 57 | Dma_request_msc2_out = 30, |
paul@214 | 58 | Dma_request_msc2_in = 31, |
paul@214 | 59 | Dma_request_pcm0_out = 32, |
paul@214 | 60 | Dma_request_pcm0_in = 33, |
paul@214 | 61 | Dma_request_i2c0_out = 36, |
paul@214 | 62 | Dma_request_i2c0_in = 37, |
paul@214 | 63 | Dma_request_i2c1_out = 38, |
paul@214 | 64 | Dma_request_i2c1_in = 39, |
paul@214 | 65 | Dma_request_i2c2_out = 40, |
paul@214 | 66 | Dma_request_i2c2_in = 41, |
paul@214 | 67 | Dma_request_i2c3_out = 42, |
paul@214 | 68 | Dma_request_i2c3_in = 43, |
paul@214 | 69 | Dma_request_i2c4_out = 44, |
paul@214 | 70 | Dma_request_i2c4_in = 45, |
paul@214 | 71 | Dma_request_des_out = 46, |
paul@214 | 72 | Dma_request_des_in = 47, |
paul@214 | 73 | }; |
paul@214 | 74 | |
paul@214 | 75 | |
paul@214 | 76 | |
paul@214 | 77 | #ifdef __cplusplus |
paul@214 | 78 | |
paul@214 | 79 | #include <l4/devices/cpm-jz4780.h> |
paul@214 | 80 | #include <l4/devices/hw_mmio_register_block.h> |
paul@214 | 81 | |
paul@214 | 82 | // Forward declaration. |
paul@214 | 83 | |
paul@214 | 84 | class Dma_jz4780_chip; |
paul@214 | 85 | |
paul@214 | 86 | |
paul@214 | 87 | |
paul@214 | 88 | // DMA channel. |
paul@214 | 89 | |
paul@214 | 90 | class Dma_jz4780_channel |
paul@214 | 91 | { |
paul@214 | 92 | private: |
paul@214 | 93 | Hw::Register_block<32> _regs; |
paul@214 | 94 | Dma_jz4780_chip *_chip; |
paul@214 | 95 | uint8_t _channel; |
paul@214 | 96 | l4_cap_idx_t _irq = L4_INVALID_CAP; |
paul@214 | 97 | |
paul@214 | 98 | public: |
paul@214 | 99 | Dma_jz4780_channel(Dma_jz4780_chip *chip, uint8_t channel, l4_addr_t start, l4_cap_idx_t irq); |
paul@214 | 100 | |
paul@214 | 101 | unsigned int transfer(uint32_t source, uint32_t destination, |
paul@214 | 102 | unsigned int count, |
paul@214 | 103 | bool source_increment, bool destination_increment, |
paul@214 | 104 | uint8_t source_width, uint8_t destination_width, |
paul@214 | 105 | uint8_t transfer_unit_size, |
paul@214 | 106 | enum Dma_jz4780_request_type type=Dma_request_auto); |
paul@214 | 107 | |
paul@214 | 108 | unsigned int wait(); |
paul@214 | 109 | |
paul@214 | 110 | protected: |
paul@214 | 111 | // Transfer property configuration. |
paul@214 | 112 | |
paul@214 | 113 | uint32_t encode_req_detect_int_length(uint8_t units); |
paul@214 | 114 | |
paul@214 | 115 | uint32_t encode_source_port_width(uint8_t width); |
paul@214 | 116 | |
paul@214 | 117 | uint32_t encode_destination_port_width(uint8_t width); |
paul@214 | 118 | |
paul@214 | 119 | uint32_t encode_transfer_unit_size(uint8_t size); |
paul@214 | 120 | |
paul@214 | 121 | // Transaction control. |
paul@214 | 122 | |
paul@214 | 123 | void ack_irq(); |
paul@214 | 124 | |
paul@214 | 125 | bool completed(); |
paul@214 | 126 | |
paul@214 | 127 | bool error(); |
paul@214 | 128 | |
paul@214 | 129 | bool halted(); |
paul@214 | 130 | |
paul@214 | 131 | bool wait_for_irq(); |
paul@214 | 132 | |
paul@214 | 133 | bool wait_for_irq(unsigned int timeout); |
paul@214 | 134 | }; |
paul@214 | 135 | |
paul@214 | 136 | // DMA device control. |
paul@214 | 137 | |
paul@214 | 138 | class Dma_jz4780_chip |
paul@214 | 139 | { |
paul@214 | 140 | private: |
paul@214 | 141 | Hw::Register_block<32> _regs; |
paul@214 | 142 | l4_addr_t _start, _end; |
paul@214 | 143 | Cpm_jz4780_chip *_cpm; |
paul@214 | 144 | |
paul@214 | 145 | public: |
paul@214 | 146 | Dma_jz4780_chip(l4_addr_t start, l4_addr_t end, Cpm_jz4780_chip *cpm); |
paul@214 | 147 | |
paul@214 | 148 | void disable(); |
paul@214 | 149 | |
paul@214 | 150 | void enable(); |
paul@214 | 151 | |
paul@214 | 152 | Dma_jz4780_channel *get_channel(uint8_t channel, l4_cap_idx_t irq); |
paul@214 | 153 | |
paul@214 | 154 | // Transaction control. |
paul@214 | 155 | |
paul@214 | 156 | void ack_irq(uint8_t channel); |
paul@214 | 157 | |
paul@214 | 158 | bool error(); |
paul@214 | 159 | |
paul@214 | 160 | bool halted(); |
paul@214 | 161 | |
paul@214 | 162 | bool have_interrupt(uint8_t channel); |
paul@214 | 163 | }; |
paul@214 | 164 | |
paul@214 | 165 | #endif /* __cplusplus */ |
paul@214 | 166 | |
paul@214 | 167 | |
paul@214 | 168 | |
paul@214 | 169 | /* C language interface. */ |
paul@214 | 170 | |
paul@214 | 171 | EXTERN_C_BEGIN |
paul@214 | 172 | |
paul@214 | 173 | void *jz4780_dma_init(l4_addr_t start, l4_addr_t end, void *cpm); |
paul@214 | 174 | |
paul@214 | 175 | void jz4780_dma_disable(void *dma_chip); |
paul@214 | 176 | |
paul@214 | 177 | void jz4780_dma_enable(void *dma_chip); |
paul@214 | 178 | |
paul@214 | 179 | void *jz4780_dma_get_channel(void *dma, uint8_t channel, l4_cap_idx_t irq); |
paul@214 | 180 | |
paul@214 | 181 | unsigned int jz4780_dma_transfer(void *dma_channel, |
paul@214 | 182 | uint32_t source, uint32_t destination, |
paul@214 | 183 | unsigned int count, |
paul@214 | 184 | int source_increment, int destination_increment, |
paul@214 | 185 | uint8_t source_width, uint8_t destination_width, |
paul@214 | 186 | uint8_t transfer_unit_size, |
paul@214 | 187 | enum Dma_jz4780_request_type type); |
paul@214 | 188 | |
paul@214 | 189 | unsigned int jz4780_dma_wait(void *dma_channel); |
paul@214 | 190 | |
paul@214 | 191 | EXTERN_C_END |