1.1 --- a/pkg/devices/lib/dma/src/jz4730.cc Tue Oct 24 17:22:51 2023 +0200
1.2 +++ b/pkg/devices/lib/dma/src/jz4730.cc Tue Oct 24 17:32:54 2023 +0200
1.3 @@ -27,7 +27,9 @@
1.4 #include <l4/sys/irq.h>
1.5 #include <l4/util/util.h>
1.6
1.7 -#include <cstdio>
1.8 +#include <stdio.h>
1.9 +
1.10 +
1.11
1.12 enum Global_regs
1.13 {
1.14 @@ -96,7 +98,16 @@
1.15 enum Dma_control_status_bits : unsigned
1.16 {
1.17 Dma_source_address_incr = 0x00800000,
1.18 + Dma_source_address_no_incr = 0x00000000,
1.19 Dma_dest_address_incr = 0x00400000,
1.20 + Dma_dest_address_no_incr = 0x00000000,
1.21 +
1.22 + Dma_trans_unit_size_32_bit = 0x00000000,
1.23 + Dma_trans_unit_size_8_bit = 0x00000100,
1.24 + Dma_trans_unit_size_16_bit = 0x00000200,
1.25 + Dma_trans_unit_size_16_byte = 0x00000300,
1.26 + Dma_trans_unit_size_32_byte = 0x00000400,
1.27 +
1.28 Dma_address_error = 0x00000010,
1.29 Dma_trans_completed = 0x00000008,
1.30 Dma_trans_halted = 0x00000004,
1.31 @@ -142,62 +153,6 @@
1.32 ((external ? (int) _ext_end_of_process_mode : 0) << Dma_ext_end_of_process_mode);
1.33 }
1.34
1.35 -// Encode the appropriate source address increment for the given request type.
1.36 -// Here, memory-to-memory transfers and transfers to peripherals involve an
1.37 -// incrementing source address. Transfers from peripherals involve a static
1.38 -// source address.
1.39 -
1.40 -uint32_t
1.41 -Dma_jz4730_channel::encode_source_address_increment(enum Dma_jz4730_request_type type)
1.42 -{
1.43 - switch (type)
1.44 - {
1.45 - case Dma_request_auto:
1.46 - case Dma_request_pcmcia_out:
1.47 - case Dma_request_des_out:
1.48 - case Dma_request_uart3_out:
1.49 - case Dma_request_uart2_out:
1.50 - case Dma_request_uart1_out:
1.51 - case Dma_request_uart0_out:
1.52 - case Dma_request_ssi_send_empty:
1.53 - case Dma_request_aic_send_empty:
1.54 - case Dma_request_msc_send_empty:
1.55 - case Dma_request_ost2_underflow:
1.56 - return Dma_source_address_incr;
1.57 -
1.58 - default:
1.59 - return 0;
1.60 - }
1.61 -}
1.62 -
1.63 -// Encode the appropriate destination address increment for the given request
1.64 -// type. Here, memory-to-memory transfers and transfers from peripherals involve
1.65 -// an incrementing destination address. Transfers to peripherals involve a static
1.66 -// destination address.
1.67 -
1.68 -uint32_t
1.69 -Dma_jz4730_channel::encode_destination_address_increment(enum Dma_jz4730_request_type type)
1.70 -{
1.71 - switch (type)
1.72 - {
1.73 - case Dma_request_auto:
1.74 - case Dma_request_pcmcia_in:
1.75 - case Dma_request_des_in:
1.76 - case Dma_request_uart3_in:
1.77 - case Dma_request_uart2_in:
1.78 - case Dma_request_uart1_in:
1.79 - case Dma_request_uart0_in:
1.80 - case Dma_request_ssi_recv_full:
1.81 - case Dma_request_aic_recv_full:
1.82 - case Dma_request_msc_recv_full:
1.83 - case Dma_request_ost2_underflow:
1.84 - return Dma_dest_address_incr;
1.85 -
1.86 - default:
1.87 - return 0;
1.88 - }
1.89 -}
1.90 -
1.91 // Return the closest interval length greater than or equal to the number of
1.92 // units given encoded in the request detection interval length field of the
1.93 // control/status register.
1.94 @@ -211,26 +166,23 @@
1.95 if (!units)
1.96 return 0;
1.97
1.98 - for (i = 0; i < 15; i++)
1.99 + for (i = 0; i <= 15; i++)
1.100 {
1.101 - if (lengths[i++] >= units)
1.102 + if (lengths[i] >= units)
1.103 break;
1.104 }
1.105
1.106 - return lengths[i] << Dma_req_detect_int_length;
1.107 + return i << Dma_req_detect_int_length;
1.108 }
1.109
1.110 -// Encode the appropriate source port width for the given request type.
1.111 +// Encode the appropriate source port width.
1.112
1.113 uint32_t
1.114 -Dma_jz4730_channel::encode_source_port_width(enum Dma_jz4730_request_type type)
1.115 +Dma_jz4730_channel::encode_source_port_width(uint8_t width)
1.116 {
1.117 - switch (type)
1.118 + switch (width)
1.119 {
1.120 - case Dma_request_uart3_in:
1.121 - case Dma_request_uart2_in:
1.122 - case Dma_request_uart1_in:
1.123 - case Dma_request_uart0_in:
1.124 + case 1:
1.125 return Dma_port_width_8_bit << Dma_source_port_width;
1.126
1.127 default:
1.128 @@ -241,14 +193,11 @@
1.129 // Encode the appropriate destination port width for the given request type.
1.130
1.131 uint32_t
1.132 -Dma_jz4730_channel::encode_destination_port_width(enum Dma_jz4730_request_type type)
1.133 +Dma_jz4730_channel::encode_destination_port_width(uint8_t width)
1.134 {
1.135 - switch (type)
1.136 + switch (width)
1.137 {
1.138 - case Dma_request_uart3_out:
1.139 - case Dma_request_uart2_out:
1.140 - case Dma_request_uart1_out:
1.141 - case Dma_request_uart0_out:
1.142 + case 1:
1.143 return Dma_port_width_8_bit << Dma_dest_port_width;
1.144
1.145 default:
1.146 @@ -256,12 +205,38 @@
1.147 }
1.148 }
1.149
1.150 +// Encode the transfer unit size.
1.151 +
1.152 +uint32_t
1.153 +Dma_jz4730_channel::encode_transfer_unit_size(uint8_t size)
1.154 +{
1.155 + switch (size)
1.156 + {
1.157 + case 1:
1.158 + return Dma_trans_unit_size_8_bit;
1.159 +
1.160 + case 2:
1.161 + return Dma_trans_unit_size_16_bit;
1.162 +
1.163 + case 16:
1.164 + return Dma_trans_unit_size_16_byte;
1.165 +
1.166 + case 32:
1.167 + return Dma_trans_unit_size_32_byte;
1.168 +
1.169 + default:
1.170 + return Dma_trans_unit_size_32_bit;
1.171 + }
1.172 +}
1.173 +
1.174 // Transfer data between memory locations.
1.175
1.176 unsigned int
1.177 Dma_jz4730_channel::transfer(uint32_t source, uint32_t destination,
1.178 unsigned int count,
1.179 - enum Dma_jz4730_trans_unit_size size,
1.180 + bool source_increment, bool destination_increment,
1.181 + uint8_t source_width, uint8_t destination_width,
1.182 + uint8_t transfer_unit_size,
1.183 enum Dma_jz4730_request_type type)
1.184 {
1.185 // Ensure an absence of address error and halt conditions globally and in this channel.
1.186 @@ -285,7 +260,9 @@
1.187
1.188 // Set transfer count to the number of units.
1.189
1.190 - _regs[Dma_transfer_count] = count;
1.191 + unsigned int units = count < Dma_transfer_count_mask ? count : Dma_transfer_count_mask;
1.192 +
1.193 + _regs[Dma_transfer_count] = units;
1.194
1.195 // Set auto-request for memory-to-memory transfers. Otherwise, set the
1.196 // indicated request type.
1.197 @@ -303,19 +280,27 @@
1.198 */
1.199
1.200 _regs[Dma_control_status] = encode_external_transfer(type) |
1.201 - encode_source_address_increment(type) |
1.202 - encode_destination_address_increment(type) |
1.203 - encode_source_port_width(type) |
1.204 - encode_destination_port_width(type) |
1.205 - (size << Dma_trans_unit_size) |
1.206 + (source_increment ? Dma_source_address_incr : Dma_source_address_no_incr) |
1.207 + (destination_increment ? Dma_dest_address_incr : Dma_dest_address_no_incr) |
1.208 + encode_source_port_width(source_width) |
1.209 + encode_destination_port_width(destination_width) |
1.210 + encode_transfer_unit_size(transfer_unit_size) |
1.211 (Dma_trans_mode_single << Dma_trans_mode) |
1.212 Dma_channel_irq_enable |
1.213 Dma_channel_enable;
1.214
1.215 + // Return the number of units to transfer.
1.216 +
1.217 + return units;
1.218 +}
1.219 +
1.220 +unsigned int
1.221 +Dma_jz4730_channel::wait()
1.222 +{
1.223 // An interrupt will occur upon completion, the completion flag will be set
1.224 // and the transfer count will be zero.
1.225
1.226 - unsigned int remaining = count;
1.227 + unsigned int remaining = 0;
1.228
1.229 do
1.230 {
1.231 @@ -334,9 +319,16 @@
1.232 }
1.233 while (!error() && !halted() && !completed());
1.234
1.235 - // Return the number of transferred units.
1.236 + // Reset the channel status.
1.237
1.238 - return count - remaining;
1.239 + _regs[Dma_control_status] = _regs[Dma_control_status] & ~(Dma_channel_enable |
1.240 + Dma_trans_completed | Dma_address_error |
1.241 + Dma_trans_halted);
1.242 + _regs[Dma_transfer_count] = 0;
1.243 +
1.244 + // Return the number of remaining units.
1.245 +
1.246 + return remaining;
1.247 }
1.248
1.249 // Wait indefinitely for an interrupt request, returning true if one was delivered.
1.250 @@ -424,7 +416,7 @@
1.251 while (_regs[Dma_control] & Dma_control_enable);
1.252 }
1.253
1.254 -// Obtain a channel object. Only one channel is supported.
1.255 +// Obtain a channel object.
1.256
1.257 Dma_jz4730_channel *
1.258 Dma_jz4730_chip::get_channel(uint8_t channel, l4_cap_idx_t irq)
1.259 @@ -487,10 +479,20 @@
1.260 static_cast<Dma_jz4730_channel *>(dma_channel)->set_req_detect_mode(mode);
1.261 }
1.262
1.263 -unsigned int jz4730_dma_transfer(void *dma_channel, uint32_t source,
1.264 - uint32_t destination, unsigned int count,
1.265 - enum Dma_jz4730_trans_unit_size size,
1.266 +unsigned int jz4730_dma_transfer(void *dma_channel,
1.267 + uint32_t source, uint32_t destination,
1.268 + unsigned int count,
1.269 + int source_increment, int destination_increment,
1.270 + uint8_t source_width, uint8_t destination_width,
1.271 + uint8_t transfer_unit_size,
1.272 enum Dma_jz4730_request_type type)
1.273 {
1.274 - return static_cast<Dma_jz4730_channel *>(dma_channel)->transfer(source, destination, count, size, type);
1.275 + return static_cast<Dma_jz4730_channel *>(dma_channel)->transfer(source,
1.276 + destination, count, source_increment, destination_increment, source_width,
1.277 + destination_width, transfer_unit_size, type);
1.278 }
1.279 +
1.280 +unsigned int jz4730_dma_wait(void *dma_channel)
1.281 +{
1.282 + return static_cast<Dma_jz4730_channel *>(dma_channel)->wait();
1.283 +}