paul@204 | 1 | /* |
paul@204 | 2 | * DMA support for the X1600. |
paul@204 | 3 | * |
paul@204 | 4 | * Copyright (C) 2021, 2023 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@204 | 72 | |
paul@204 | 73 | |
paul@204 | 74 | #ifdef __cplusplus |
paul@204 | 75 | |
paul@204 | 76 | #include <l4/devices/cpm-x1600.h> |
paul@204 | 77 | #include <l4/devices/hw_mmio_register_block.h> |
paul@204 | 78 | |
paul@204 | 79 | // Forward declaration. |
paul@204 | 80 | |
paul@204 | 81 | class Dma_x1600_chip; |
paul@204 | 82 | |
paul@204 | 83 | |
paul@204 | 84 | |
paul@204 | 85 | // DMA channel. |
paul@204 | 86 | |
paul@204 | 87 | class Dma_x1600_channel |
paul@204 | 88 | { |
paul@204 | 89 | private: |
paul@204 | 90 | Hw::Register_block<32> _regs; |
paul@204 | 91 | Dma_x1600_chip *_chip; |
paul@204 | 92 | uint8_t _channel; |
paul@204 | 93 | l4_cap_idx_t _irq = L4_INVALID_CAP; |
paul@204 | 94 | |
paul@204 | 95 | public: |
paul@204 | 96 | Dma_x1600_channel(Dma_x1600_chip *chip, uint8_t channel, l4_addr_t start, l4_cap_idx_t irq); |
paul@204 | 97 | |
paul@204 | 98 | unsigned int transfer(uint32_t source, uint32_t destination, |
paul@204 | 99 | unsigned int count, |
paul@204 | 100 | bool source_increment, bool destination_increment, |
paul@204 | 101 | uint8_t source_width, uint8_t destination_width, |
paul@204 | 102 | uint8_t transfer_unit_size, |
paul@204 | 103 | enum Dma_x1600_request_type type=Dma_request_auto); |
paul@204 | 104 | |
paul@204 | 105 | unsigned int wait(); |
paul@204 | 106 | |
paul@204 | 107 | protected: |
paul@204 | 108 | // Transfer property configuration. |
paul@204 | 109 | |
paul@204 | 110 | uint32_t encode_req_detect_int_length(uint8_t units); |
paul@204 | 111 | |
paul@204 | 112 | uint32_t encode_source_port_width(uint8_t width); |
paul@204 | 113 | |
paul@204 | 114 | uint32_t encode_destination_port_width(uint8_t width); |
paul@204 | 115 | |
paul@204 | 116 | uint32_t encode_transfer_unit_size(uint8_t size); |
paul@204 | 117 | |
paul@204 | 118 | // Transaction control. |
paul@204 | 119 | |
paul@204 | 120 | void ack_irq(); |
paul@204 | 121 | |
paul@204 | 122 | bool completed(); |
paul@204 | 123 | |
paul@204 | 124 | bool error(); |
paul@204 | 125 | |
paul@204 | 126 | bool halted(); |
paul@204 | 127 | |
paul@204 | 128 | bool wait_for_irq(); |
paul@204 | 129 | |
paul@204 | 130 | bool wait_for_irq(unsigned int timeout); |
paul@204 | 131 | }; |
paul@204 | 132 | |
paul@204 | 133 | // DMA device control. |
paul@204 | 134 | |
paul@204 | 135 | class Dma_x1600_chip |
paul@204 | 136 | { |
paul@204 | 137 | private: |
paul@204 | 138 | Hw::Register_block<32> _regs; |
paul@204 | 139 | l4_addr_t _start, _end; |
paul@204 | 140 | Cpm_x1600_chip *_cpm; |
paul@204 | 141 | |
paul@204 | 142 | public: |
paul@204 | 143 | Dma_x1600_chip(l4_addr_t start, l4_addr_t end, Cpm_x1600_chip *cpm); |
paul@204 | 144 | |
paul@204 | 145 | void disable(); |
paul@204 | 146 | |
paul@204 | 147 | void enable(); |
paul@204 | 148 | |
paul@204 | 149 | Dma_x1600_channel *get_channel(uint8_t channel, l4_cap_idx_t irq); |
paul@204 | 150 | |
paul@204 | 151 | // Transaction control. |
paul@204 | 152 | |
paul@204 | 153 | void ack_irq(uint8_t channel); |
paul@204 | 154 | |
paul@204 | 155 | bool error(); |
paul@204 | 156 | |
paul@204 | 157 | bool halted(); |
paul@204 | 158 | |
paul@204 | 159 | bool have_interrupt(uint8_t channel); |
paul@204 | 160 | }; |
paul@204 | 161 | |
paul@204 | 162 | #endif /* __cplusplus */ |
paul@204 | 163 | |
paul@204 | 164 | |
paul@204 | 165 | |
paul@204 | 166 | /* C language interface. */ |
paul@204 | 167 | |
paul@204 | 168 | EXTERN_C_BEGIN |
paul@204 | 169 | |
paul@204 | 170 | void *x1600_dma_init(l4_addr_t start, l4_addr_t end, void *cpm); |
paul@204 | 171 | |
paul@204 | 172 | void x1600_dma_disable(void *dma_chip); |
paul@204 | 173 | |
paul@204 | 174 | void x1600_dma_enable(void *dma_chip); |
paul@204 | 175 | |
paul@204 | 176 | void *x1600_dma_get_channel(void *dma, uint8_t channel, l4_cap_idx_t irq); |
paul@204 | 177 | |
paul@204 | 178 | unsigned int x1600_dma_transfer(void *dma_channel, |
paul@204 | 179 | uint32_t source, uint32_t destination, |
paul@204 | 180 | unsigned int count, |
paul@204 | 181 | int source_increment, int destination_increment, |
paul@204 | 182 | uint8_t source_width, uint8_t destination_width, |
paul@204 | 183 | uint8_t transfer_unit_size, |
paul@204 | 184 | enum Dma_x1600_request_type type); |
paul@204 | 185 | |
paul@204 | 186 | unsigned int x1600_dma_wait(void *dma_channel); |
paul@204 | 187 | |
paul@204 | 188 | EXTERN_C_END |