1.1 --- a/pkg/devices/lib/dma/src/jz4780.cc Thu Nov 09 18:40:31 2023 +0100
1.2 +++ b/pkg/devices/lib/dma/src/jz4780.cc Fri Nov 10 02:02:11 2023 +0100
1.3 @@ -23,6 +23,7 @@
1.4 #include <l4/devices/dma-jz4780.h>
1.5 #include <l4/devices/hw_mmio_register_block.h>
1.6
1.7 +#include <l4/sys/cache.h>
1.8 #include <l4/sys/icu.h>
1.9 #include <l4/sys/ipc.h>
1.10 #include <l4/sys/irq.h>
1.11 @@ -36,6 +37,13 @@
1.12 {
1.13 Dma_control = 0x1000, // DMAC
1.14 Dma_irq_pending = 0x1004, // DIRQP
1.15 + Dma_doorbell = 0x1008, // DDB
1.16 + Dma_doorbell_set = 0x100c, // DDS
1.17 + Dma_channel_programmable = 0x101c, // DMACP
1.18 + Dma_soft_irq_pending = 0x1020, // DSIRQP
1.19 + Dma_soft_irq_mask = 0x1024, // DSIRQM
1.20 + Dma_mcu_irq_pending = 0x1028, // DCIRQP
1.21 + Dma_mcu_irq_mask = 0x102c, // DCIRQM
1.22 };
1.23
1.24 enum Channel_regs
1.25 @@ -69,7 +77,10 @@
1.26
1.27 enum Dma_transfer_count_bits : unsigned
1.28 {
1.29 + Dma_descriptor_offset_mask = 0xff000000, // DOA (in DES3)
1.30 Dma_transfer_count_mask = 0x00ffffff,
1.31 +
1.32 + Dma_descriptor_offset_shift = 24,
1.33 };
1.34
1.35 enum Dma_request_source_bits : unsigned
1.36 @@ -81,6 +92,7 @@
1.37 {
1.38 Dma_no_descriptor_transfer = 0x80000000,
1.39 Dma_8word_descriptor = 0x40000000,
1.40 + Dma_4word_descriptor = 0x00000000,
1.41 Dma_copy_offset_mask = 0x0000ff00,
1.42 Dma_address_error = 0x00000010,
1.43 Dma_trans_completed = 0x00000008,
1.44 @@ -253,7 +265,9 @@
1.45 bool source_increment, bool destination_increment,
1.46 uint8_t source_width, uint8_t destination_width,
1.47 uint8_t transfer_unit_size,
1.48 - enum Dma_jz4780_request_type type)
1.49 + enum Dma_jz4780_request_type type,
1.50 + l4_addr_t desc_vaddr,
1.51 + l4re_dma_space_dma_addr_t desc_paddr)
1.52 {
1.53 printf("transfer:%s%s%s%s\n", error() ? " error" : "",
1.54 halted() ? " halted" : "",
1.55 @@ -274,43 +288,65 @@
1.56
1.57 _regs[Dma_control_status] = _regs[Dma_control_status] & ~Dma_channel_enable;
1.58
1.59 - // Set addresses.
1.60 -
1.61 - _regs[Dma_source] = source;
1.62 - _regs[Dma_destination] = destination;
1.63 -
1.64 // Set transfer count to the number of units.
1.65
1.66 unsigned int units = count < Dma_transfer_count_mask ? count : Dma_transfer_count_mask;
1.67
1.68 - _regs[Dma_transfer_count] = units;
1.69 + // NOTE: Request detection interval length (for autonomous mode) not considered.
1.70
1.71 - // Set auto-request for memory-to-memory transfers. Otherwise, set the
1.72 - // indicated request type.
1.73 + uint32_t command = (source_increment ? Dma_source_address_increment :
1.74 + Dma_source_address_no_increment) |
1.75 + (destination_increment ? Dma_destination_address_increment :
1.76 + Dma_destination_address_no_increment) |
1.77 + encode_source_port_width(source_width) |
1.78 + encode_destination_port_width(destination_width) |
1.79 + encode_transfer_unit_size(transfer_unit_size) |
1.80 + Dma_transfer_irq_enable;
1.81
1.82 - _regs[Dma_request_source] = type;
1.83 + // Populate the descriptor, largely corresponding to the population of
1.84 + // registers when descriptors are not being used.
1.85
1.86 - // For a descriptor, the actual fields would be populated instead of the
1.87 - // command register, descriptor transfer would be indicated in the control/
1.88 - // status register along with the appropriate descriptor size indicator.
1.89 + if (desc_vaddr)
1.90 + {
1.91 + struct jz4780_dma_descriptor *desc = (struct jz4780_dma_descriptor *) desc_vaddr;
1.92 +
1.93 + // NOTE: Linking to the same descriptor.
1.94 +
1.95 + uint32_t descriptor_offset = 0;
1.96
1.97 - /* NOTE: To be considered...
1.98 - * request detection interval length (for autonomous mode)
1.99 - */
1.100 + desc->command = command | Dma_descriptor_link_enable;
1.101 + desc->source = source;
1.102 + desc->destination = destination;
1.103 + desc->transfer_count = (units & Dma_transfer_count_mask) |
1.104 + (descriptor_offset << Dma_descriptor_offset_shift);
1.105 + desc->request_source = type;
1.106 +
1.107 + // NOTE: Stride not supported yet.
1.108 +
1.109 + l4_cache_clean_data((unsigned long) desc_vaddr,
1.110 + (unsigned long) desc_vaddr + sizeof(*desc));
1.111 +
1.112 + // Commit the descriptor.
1.113
1.114 - _regs[Dma_command] = (source_increment ? Dma_source_address_increment : Dma_source_address_no_increment) |
1.115 - (destination_increment ? Dma_destination_address_increment : Dma_destination_address_no_increment) |
1.116 - encode_source_port_width(source_width) |
1.117 - encode_destination_port_width(destination_width) |
1.118 - encode_transfer_unit_size(transfer_unit_size) |
1.119 - Dma_transfer_irq_enable;
1.120 + _regs[Dma_descriptor_address] = desc_paddr;
1.121 + _chip->commit_descriptor(_channel);
1.122 + }
1.123 +
1.124 + // Otherwise, populate the registers for a one-off transfer.
1.125
1.126 - // For a descriptor, the descriptor address would be set and the doorbell
1.127 - // register field for the channel set.
1.128 + else
1.129 + {
1.130 + _regs[Dma_command] = command;
1.131 + _regs[Dma_source] = source;
1.132 + _regs[Dma_destination] = destination;
1.133 + _regs[Dma_transfer_count] = units & Dma_transfer_count_mask;
1.134 + _regs[Dma_request_source] = type;
1.135 + }
1.136
1.137 - // Enable the channel (and peripheral).
1.138 + // Enable the channel with descriptor transfer configured if appropriate.
1.139
1.140 - _regs[Dma_control_status] = Dma_no_descriptor_transfer |
1.141 + _regs[Dma_control_status] = (desc_vaddr ? Dma_8word_descriptor :
1.142 + Dma_no_descriptor_transfer) |
1.143 Dma_channel_enable;
1.144
1.145 // Return the number of units to transfer.
1.146 @@ -477,6 +513,12 @@
1.147 return _regs[Dma_control] & Dma_control_trans_halted ? true : false;
1.148 }
1.149
1.150 +void
1.151 +Dma_jz4780_chip::commit_descriptor(uint8_t channel)
1.152 +{
1.153 + _regs[Dma_doorbell_set] = (1 << channel);
1.154 +}
1.155 +
1.156
1.157
1.158 // C language interface functions.
1.159 @@ -502,18 +544,33 @@
1.160 }
1.161
1.162 unsigned int jz4780_dma_transfer(void *dma_channel,
1.163 - uint32_t source, uint32_t destination,
1.164 - unsigned int count,
1.165 - int source_increment, int destination_increment,
1.166 - uint8_t source_width, uint8_t destination_width,
1.167 - uint8_t transfer_unit_size,
1.168 - enum Dma_jz4780_request_type type)
1.169 + uint32_t source, uint32_t destination,
1.170 + unsigned int count,
1.171 + int source_increment, int destination_increment,
1.172 + uint8_t source_width, uint8_t destination_width,
1.173 + uint8_t transfer_unit_size,
1.174 + enum Dma_jz4780_request_type type)
1.175 {
1.176 return static_cast<Dma_jz4780_channel *>(dma_channel)->transfer(source,
1.177 destination, count, source_increment, destination_increment, source_width,
1.178 destination_width, transfer_unit_size, type);
1.179 }
1.180
1.181 +unsigned int jz4780_dma_transfer_descriptor(void *dma_channel,
1.182 + uint32_t source, uint32_t destination,
1.183 + unsigned int count,
1.184 + int source_increment, int destination_increment,
1.185 + uint8_t source_width, uint8_t destination_width,
1.186 + uint8_t transfer_unit_size,
1.187 + enum Dma_jz4780_request_type type,
1.188 + l4_addr_t desc_vaddr,
1.189 + l4re_dma_space_dma_addr_t desc_paddr)
1.190 +{
1.191 + return static_cast<Dma_jz4780_channel *>(dma_channel)->transfer(source,
1.192 + destination, count, source_increment, destination_increment, source_width,
1.193 + destination_width, transfer_unit_size, type, desc_vaddr, desc_paddr);
1.194 +}
1.195 +
1.196 unsigned int jz4780_dma_wait(void *dma_channel)
1.197 {
1.198 return static_cast<Dma_jz4780_channel *>(dma_channel)->wait();