paul@204 | 1 | /* |
paul@204 | 2 | * DMA support for the X1600. |
paul@204 | 3 | * |
paul@305 | 4 | * Copyright (C) 2021, 2023, 2024 Paul Boddie <paul@boddie.org.uk> |
paul@204 | 5 | * |
paul@204 | 6 | * This program is free software; you can redistribute it and/or |
paul@204 | 7 | * modify it under the terms of the GNU General Public License as |
paul@204 | 8 | * published by the Free Software Foundation; either version 2 of |
paul@204 | 9 | * the License, or (at your option) any later version. |
paul@204 | 10 | * |
paul@204 | 11 | * This program is distributed in the hope that it will be useful, |
paul@204 | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
paul@204 | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
paul@204 | 14 | * GNU General Public License for more details. |
paul@204 | 15 | * |
paul@204 | 16 | * You should have received a copy of the GNU General Public License |
paul@204 | 17 | * along with this program; if not, write to the Free Software |
paul@204 | 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, |
paul@204 | 19 | * Boston, MA 02110-1301, USA |
paul@204 | 20 | */ |
paul@204 | 21 | |
paul@204 | 22 | #pragma once |
paul@204 | 23 | |
paul@204 | 24 | #include <l4/sys/types.h> |
paul@204 | 25 | #include <stdint.h> |
paul@204 | 26 | |
paul@204 | 27 | |
paul@204 | 28 | |
paul@204 | 29 | /* Enumerated types for various transfer parameters. */ |
paul@204 | 30 | |
paul@204 | 31 | enum Dma_x1600_request_type |
paul@204 | 32 | { |
paul@214 | 33 | Dma_request_auto = 8, |
paul@214 | 34 | Dma_request_can0_out = 10, |
paul@214 | 35 | Dma_request_can0_in = 11, |
paul@257 | 36 | Dma_request_can1_out = 12, |
paul@257 | 37 | Dma_request_can1_in = 13, |
paul@214 | 38 | Dma_request_uart3_out = 14, |
paul@214 | 39 | Dma_request_uart3_in = 15, |
paul@214 | 40 | Dma_request_uart2_out = 16, |
paul@214 | 41 | Dma_request_uart2_in = 17, |
paul@214 | 42 | Dma_request_uart1_out = 18, |
paul@214 | 43 | Dma_request_uart1_in = 19, |
paul@214 | 44 | Dma_request_uart0_out = 20, |
paul@214 | 45 | Dma_request_uart0_in = 21, |
paul@214 | 46 | Dma_request_ssi0_out = 22, |
paul@214 | 47 | Dma_request_ssi0_in = 23, |
paul@214 | 48 | Dma_request_i2c0_out = 36, |
paul@214 | 49 | Dma_request_i2c0_in = 37, |
paul@214 | 50 | Dma_request_i2c1_out = 38, |
paul@214 | 51 | Dma_request_i2c1_in = 39, |
paul@214 | 52 | Dma_request_ssi_slv_out = 42, |
paul@214 | 53 | Dma_request_ssi_slv_in = 43, |
paul@257 | 54 | Dma_request_pwm0_out = 44, |
paul@257 | 55 | Dma_request_pwm1_out = 45, |
paul@257 | 56 | Dma_request_pwm2_out = 46, |
paul@257 | 57 | Dma_request_pwm3_out = 47, |
paul@257 | 58 | Dma_request_pwm4_out = 48, |
paul@257 | 59 | Dma_request_pwm5_out = 49, |
paul@257 | 60 | Dma_request_pwm6_out = 50, |
paul@257 | 61 | Dma_request_pwm7_out = 51, |
paul@214 | 62 | Dma_request_msc0_out = 52, |
paul@214 | 63 | Dma_request_msc0_in = 53, |
paul@214 | 64 | Dma_request_msc1_out = 54, |
paul@214 | 65 | Dma_request_msc1_in = 55, |
paul@214 | 66 | Dma_request_sadc_in = 56, |
paul@214 | 67 | Dma_request_aic_loop_out = 61, |
paul@214 | 68 | Dma_request_aic_out = 62, |
paul@214 | 69 | Dma_request_aic_in = 63, |
paul@204 | 70 | }; |
paul@204 | 71 | |
paul@284 | 72 | /* Descriptor structure. */ |
paul@284 | 73 | |
paul@284 | 74 | struct x1600_dma_descriptor |
paul@284 | 75 | { |
paul@284 | 76 | uint32_t command, source, destination, transfer_count, |
paul@284 | 77 | stride, request_source, reserved0, reserved1; |
paul@284 | 78 | }; |
paul@284 | 79 | |
paul@204 | 80 | |
paul@204 | 81 | |
paul@204 | 82 | #ifdef __cplusplus |
paul@204 | 83 | |
paul@284 | 84 | #include <l4/devices/dma-generic.h> |
paul@204 | 85 | #include <l4/devices/hw_mmio_register_block.h> |
paul@204 | 86 | |
paul@204 | 87 | // Forward declaration. |
paul@204 | 88 | |
paul@204 | 89 | class Dma_x1600_chip; |
paul@204 | 90 | |
paul@204 | 91 | |
paul@204 | 92 | |
paul@204 | 93 | // DMA channel. |
paul@204 | 94 | |
paul@284 | 95 | class Dma_x1600_channel : public Dma_channel |
paul@204 | 96 | { |
paul@204 | 97 | private: |
paul@204 | 98 | Hw::Register_block<32> _regs; |
paul@284 | 99 | Dma_chip *_chip; |
paul@204 | 100 | uint8_t _channel; |
paul@204 | 101 | l4_cap_idx_t _irq = L4_INVALID_CAP; |
paul@204 | 102 | |
paul@204 | 103 | public: |
paul@284 | 104 | Dma_x1600_channel(Dma_chip *chip, uint8_t channel, l4_addr_t start, l4_cap_idx_t irq); |
paul@204 | 105 | |
paul@204 | 106 | unsigned int transfer(uint32_t source, uint32_t destination, |
paul@204 | 107 | unsigned int count, |
paul@204 | 108 | bool source_increment, bool destination_increment, |
paul@204 | 109 | uint8_t source_width, uint8_t destination_width, |
paul@204 | 110 | uint8_t transfer_unit_size, |
paul@284 | 111 | int type=Dma_request_auto, |
paul@284 | 112 | l4_addr_t desc_vaddr = 0, |
paul@284 | 113 | l4re_dma_space_dma_addr_t desc_paddr = 0); |
paul@204 | 114 | |
paul@204 | 115 | unsigned int wait(); |
paul@204 | 116 | |
paul@204 | 117 | protected: |
paul@204 | 118 | // Transfer property configuration. |
paul@204 | 119 | |
paul@204 | 120 | uint32_t encode_req_detect_int_length(uint8_t units); |
paul@204 | 121 | |
paul@204 | 122 | uint32_t encode_source_port_width(uint8_t width); |
paul@204 | 123 | |
paul@204 | 124 | uint32_t encode_destination_port_width(uint8_t width); |
paul@204 | 125 | |
paul@204 | 126 | uint32_t encode_transfer_unit_size(uint8_t size); |
paul@204 | 127 | |
paul@204 | 128 | // Transaction control. |
paul@204 | 129 | |
paul@204 | 130 | void ack_irq(); |
paul@204 | 131 | |
paul@305 | 132 | void clear_errors(); |
paul@305 | 133 | |
paul@204 | 134 | bool completed(); |
paul@204 | 135 | |
paul@204 | 136 | bool error(); |
paul@204 | 137 | |
paul@204 | 138 | bool halted(); |
paul@204 | 139 | |
paul@204 | 140 | bool wait_for_irq(); |
paul@204 | 141 | |
paul@204 | 142 | bool wait_for_irq(unsigned int timeout); |
paul@204 | 143 | }; |
paul@204 | 144 | |
paul@204 | 145 | // DMA device control. |
paul@204 | 146 | |
paul@284 | 147 | class Dma_x1600_chip : public Dma_chip |
paul@204 | 148 | { |
paul@204 | 149 | private: |
paul@204 | 150 | Hw::Register_block<32> _regs; |
paul@204 | 151 | l4_addr_t _start, _end; |
paul@284 | 152 | Cpm_chip *_cpm; |
paul@204 | 153 | |
paul@204 | 154 | public: |
paul@284 | 155 | Dma_x1600_chip(l4_addr_t start, l4_addr_t end, Cpm_chip *cpm); |
paul@204 | 156 | |
paul@204 | 157 | void disable(); |
paul@204 | 158 | |
paul@204 | 159 | void enable(); |
paul@204 | 160 | |
paul@306 | 161 | Dma_channel *get_channel(uint8_t channel, l4_cap_idx_t irq = L4_INVALID_CAP); |
paul@204 | 162 | |
paul@204 | 163 | // Transaction control. |
paul@204 | 164 | |
paul@204 | 165 | void ack_irq(uint8_t channel); |
paul@204 | 166 | |
paul@305 | 167 | void clear_errors(); |
paul@305 | 168 | |
paul@204 | 169 | bool error(); |
paul@204 | 170 | |
paul@204 | 171 | bool halted(); |
paul@204 | 172 | |
paul@204 | 173 | bool have_interrupt(uint8_t channel); |
paul@284 | 174 | |
paul@284 | 175 | // Descriptor operations. |
paul@284 | 176 | |
paul@284 | 177 | void commit_descriptor(uint8_t channel); |
paul@204 | 178 | }; |
paul@204 | 179 | |
paul@284 | 180 | Dma_chip *x1600_dma_chip(l4_addr_t start, l4_addr_t end, Cpm_chip *cpm); |
paul@284 | 181 | |
paul@204 | 182 | #endif /* __cplusplus */ |
paul@204 | 183 | |
paul@204 | 184 | |
paul@204 | 185 | |
paul@204 | 186 | /* C language interface. */ |
paul@204 | 187 | |
paul@204 | 188 | EXTERN_C_BEGIN |
paul@204 | 189 | |
paul@204 | 190 | void *x1600_dma_init(l4_addr_t start, l4_addr_t end, void *cpm); |
paul@204 | 191 | |
paul@204 | 192 | void x1600_dma_disable(void *dma_chip); |
paul@204 | 193 | |
paul@204 | 194 | void x1600_dma_enable(void *dma_chip); |
paul@204 | 195 | |
paul@204 | 196 | void *x1600_dma_get_channel(void *dma, uint8_t channel, l4_cap_idx_t irq); |
paul@204 | 197 | |
paul@204 | 198 | unsigned int x1600_dma_transfer(void *dma_channel, |
paul@204 | 199 | uint32_t source, uint32_t destination, |
paul@204 | 200 | unsigned int count, |
paul@204 | 201 | int source_increment, int destination_increment, |
paul@204 | 202 | uint8_t source_width, uint8_t destination_width, |
paul@204 | 203 | uint8_t transfer_unit_size, |
paul@204 | 204 | enum Dma_x1600_request_type type); |
paul@204 | 205 | |
paul@204 | 206 | unsigned int x1600_dma_wait(void *dma_channel); |
paul@204 | 207 | |
paul@204 | 208 | EXTERN_C_END |