1.1 --- a/pkg/devices/lib/dma/include/dma-jz4780.h Thu Nov 09 18:40:31 2023 +0100
1.2 +++ b/pkg/devices/lib/dma/include/dma-jz4780.h Fri Nov 10 02:02:11 2023 +0100
1.3 @@ -21,6 +21,7 @@
1.4
1.5 #pragma once
1.6
1.7 +#include <l4/re/c/dma_space.h>
1.8 #include <l4/sys/types.h>
1.9 #include <stdint.h>
1.10
1.11 @@ -72,6 +73,14 @@
1.12 Dma_request_des_in = 47,
1.13 };
1.14
1.15 +/* Descriptor structure. */
1.16 +
1.17 +struct jz4780_dma_descriptor
1.18 +{
1.19 + uint32_t command, source, destination, transfer_count,
1.20 + stride, request_source, reserved0, reserved1;
1.21 +};
1.22 +
1.23
1.24
1.25 #ifdef __cplusplus
1.26 @@ -103,7 +112,9 @@
1.27 bool source_increment, bool destination_increment,
1.28 uint8_t source_width, uint8_t destination_width,
1.29 uint8_t transfer_unit_size,
1.30 - enum Dma_jz4780_request_type type=Dma_request_auto);
1.31 + enum Dma_jz4780_request_type type=Dma_request_auto,
1.32 + l4_addr_t desc_vaddr = 0,
1.33 + l4re_dma_space_dma_addr_t desc_paddr = 0);
1.34
1.35 unsigned int wait();
1.36
1.37 @@ -160,6 +171,10 @@
1.38 bool halted();
1.39
1.40 bool have_interrupt(uint8_t channel);
1.41 +
1.42 + // Descriptor operations.
1.43 +
1.44 + void commit_descriptor(uint8_t channel);
1.45 };
1.46
1.47 #endif /* __cplusplus */
1.48 @@ -186,6 +201,16 @@
1.49 uint8_t transfer_unit_size,
1.50 enum Dma_jz4780_request_type type);
1.51
1.52 +unsigned int jz4780_dma_transfer_descriptor(void *dma_channel,
1.53 + uint32_t source, uint32_t destination,
1.54 + unsigned int count,
1.55 + int source_increment, int destination_increment,
1.56 + uint8_t source_width, uint8_t destination_width,
1.57 + uint8_t transfer_unit_size,
1.58 + enum Dma_jz4780_request_type type,
1.59 + l4_addr_t desc_vaddr,
1.60 + l4re_dma_space_dma_addr_t desc_paddr);
1.61 +
1.62 unsigned int jz4780_dma_wait(void *dma_channel);
1.63
1.64 EXTERN_C_END
2.1 --- a/pkg/devices/lib/dma/src/jz4780.cc Thu Nov 09 18:40:31 2023 +0100
2.2 +++ b/pkg/devices/lib/dma/src/jz4780.cc Fri Nov 10 02:02:11 2023 +0100
2.3 @@ -23,6 +23,7 @@
2.4 #include <l4/devices/dma-jz4780.h>
2.5 #include <l4/devices/hw_mmio_register_block.h>
2.6
2.7 +#include <l4/sys/cache.h>
2.8 #include <l4/sys/icu.h>
2.9 #include <l4/sys/ipc.h>
2.10 #include <l4/sys/irq.h>
2.11 @@ -36,6 +37,13 @@
2.12 {
2.13 Dma_control = 0x1000, // DMAC
2.14 Dma_irq_pending = 0x1004, // DIRQP
2.15 + Dma_doorbell = 0x1008, // DDB
2.16 + Dma_doorbell_set = 0x100c, // DDS
2.17 + Dma_channel_programmable = 0x101c, // DMACP
2.18 + Dma_soft_irq_pending = 0x1020, // DSIRQP
2.19 + Dma_soft_irq_mask = 0x1024, // DSIRQM
2.20 + Dma_mcu_irq_pending = 0x1028, // DCIRQP
2.21 + Dma_mcu_irq_mask = 0x102c, // DCIRQM
2.22 };
2.23
2.24 enum Channel_regs
2.25 @@ -69,7 +77,10 @@
2.26
2.27 enum Dma_transfer_count_bits : unsigned
2.28 {
2.29 + Dma_descriptor_offset_mask = 0xff000000, // DOA (in DES3)
2.30 Dma_transfer_count_mask = 0x00ffffff,
2.31 +
2.32 + Dma_descriptor_offset_shift = 24,
2.33 };
2.34
2.35 enum Dma_request_source_bits : unsigned
2.36 @@ -81,6 +92,7 @@
2.37 {
2.38 Dma_no_descriptor_transfer = 0x80000000,
2.39 Dma_8word_descriptor = 0x40000000,
2.40 + Dma_4word_descriptor = 0x00000000,
2.41 Dma_copy_offset_mask = 0x0000ff00,
2.42 Dma_address_error = 0x00000010,
2.43 Dma_trans_completed = 0x00000008,
2.44 @@ -253,7 +265,9 @@
2.45 bool source_increment, bool destination_increment,
2.46 uint8_t source_width, uint8_t destination_width,
2.47 uint8_t transfer_unit_size,
2.48 - enum Dma_jz4780_request_type type)
2.49 + enum Dma_jz4780_request_type type,
2.50 + l4_addr_t desc_vaddr,
2.51 + l4re_dma_space_dma_addr_t desc_paddr)
2.52 {
2.53 printf("transfer:%s%s%s%s\n", error() ? " error" : "",
2.54 halted() ? " halted" : "",
2.55 @@ -274,43 +288,65 @@
2.56
2.57 _regs[Dma_control_status] = _regs[Dma_control_status] & ~Dma_channel_enable;
2.58
2.59 - // Set addresses.
2.60 -
2.61 - _regs[Dma_source] = source;
2.62 - _regs[Dma_destination] = destination;
2.63 -
2.64 // Set transfer count to the number of units.
2.65
2.66 unsigned int units = count < Dma_transfer_count_mask ? count : Dma_transfer_count_mask;
2.67
2.68 - _regs[Dma_transfer_count] = units;
2.69 + // NOTE: Request detection interval length (for autonomous mode) not considered.
2.70
2.71 - // Set auto-request for memory-to-memory transfers. Otherwise, set the
2.72 - // indicated request type.
2.73 + uint32_t command = (source_increment ? Dma_source_address_increment :
2.74 + Dma_source_address_no_increment) |
2.75 + (destination_increment ? Dma_destination_address_increment :
2.76 + Dma_destination_address_no_increment) |
2.77 + encode_source_port_width(source_width) |
2.78 + encode_destination_port_width(destination_width) |
2.79 + encode_transfer_unit_size(transfer_unit_size) |
2.80 + Dma_transfer_irq_enable;
2.81
2.82 - _regs[Dma_request_source] = type;
2.83 + // Populate the descriptor, largely corresponding to the population of
2.84 + // registers when descriptors are not being used.
2.85
2.86 - // For a descriptor, the actual fields would be populated instead of the
2.87 - // command register, descriptor transfer would be indicated in the control/
2.88 - // status register along with the appropriate descriptor size indicator.
2.89 + if (desc_vaddr)
2.90 + {
2.91 + struct jz4780_dma_descriptor *desc = (struct jz4780_dma_descriptor *) desc_vaddr;
2.92 +
2.93 + // NOTE: Linking to the same descriptor.
2.94 +
2.95 + uint32_t descriptor_offset = 0;
2.96
2.97 - /* NOTE: To be considered...
2.98 - * request detection interval length (for autonomous mode)
2.99 - */
2.100 + desc->command = command | Dma_descriptor_link_enable;
2.101 + desc->source = source;
2.102 + desc->destination = destination;
2.103 + desc->transfer_count = (units & Dma_transfer_count_mask) |
2.104 + (descriptor_offset << Dma_descriptor_offset_shift);
2.105 + desc->request_source = type;
2.106 +
2.107 + // NOTE: Stride not supported yet.
2.108 +
2.109 + l4_cache_clean_data((unsigned long) desc_vaddr,
2.110 + (unsigned long) desc_vaddr + sizeof(*desc));
2.111 +
2.112 + // Commit the descriptor.
2.113
2.114 - _regs[Dma_command] = (source_increment ? Dma_source_address_increment : Dma_source_address_no_increment) |
2.115 - (destination_increment ? Dma_destination_address_increment : Dma_destination_address_no_increment) |
2.116 - encode_source_port_width(source_width) |
2.117 - encode_destination_port_width(destination_width) |
2.118 - encode_transfer_unit_size(transfer_unit_size) |
2.119 - Dma_transfer_irq_enable;
2.120 + _regs[Dma_descriptor_address] = desc_paddr;
2.121 + _chip->commit_descriptor(_channel);
2.122 + }
2.123 +
2.124 + // Otherwise, populate the registers for a one-off transfer.
2.125
2.126 - // For a descriptor, the descriptor address would be set and the doorbell
2.127 - // register field for the channel set.
2.128 + else
2.129 + {
2.130 + _regs[Dma_command] = command;
2.131 + _regs[Dma_source] = source;
2.132 + _regs[Dma_destination] = destination;
2.133 + _regs[Dma_transfer_count] = units & Dma_transfer_count_mask;
2.134 + _regs[Dma_request_source] = type;
2.135 + }
2.136
2.137 - // Enable the channel (and peripheral).
2.138 + // Enable the channel with descriptor transfer configured if appropriate.
2.139
2.140 - _regs[Dma_control_status] = Dma_no_descriptor_transfer |
2.141 + _regs[Dma_control_status] = (desc_vaddr ? Dma_8word_descriptor :
2.142 + Dma_no_descriptor_transfer) |
2.143 Dma_channel_enable;
2.144
2.145 // Return the number of units to transfer.
2.146 @@ -477,6 +513,12 @@
2.147 return _regs[Dma_control] & Dma_control_trans_halted ? true : false;
2.148 }
2.149
2.150 +void
2.151 +Dma_jz4780_chip::commit_descriptor(uint8_t channel)
2.152 +{
2.153 + _regs[Dma_doorbell_set] = (1 << channel);
2.154 +}
2.155 +
2.156
2.157
2.158 // C language interface functions.
2.159 @@ -502,18 +544,33 @@
2.160 }
2.161
2.162 unsigned int jz4780_dma_transfer(void *dma_channel,
2.163 - uint32_t source, uint32_t destination,
2.164 - unsigned int count,
2.165 - int source_increment, int destination_increment,
2.166 - uint8_t source_width, uint8_t destination_width,
2.167 - uint8_t transfer_unit_size,
2.168 - enum Dma_jz4780_request_type type)
2.169 + uint32_t source, uint32_t destination,
2.170 + unsigned int count,
2.171 + int source_increment, int destination_increment,
2.172 + uint8_t source_width, uint8_t destination_width,
2.173 + uint8_t transfer_unit_size,
2.174 + enum Dma_jz4780_request_type type)
2.175 {
2.176 return static_cast<Dma_jz4780_channel *>(dma_channel)->transfer(source,
2.177 destination, count, source_increment, destination_increment, source_width,
2.178 destination_width, transfer_unit_size, type);
2.179 }
2.180
2.181 +unsigned int jz4780_dma_transfer_descriptor(void *dma_channel,
2.182 + uint32_t source, uint32_t destination,
2.183 + unsigned int count,
2.184 + int source_increment, int destination_increment,
2.185 + uint8_t source_width, uint8_t destination_width,
2.186 + uint8_t transfer_unit_size,
2.187 + enum Dma_jz4780_request_type type,
2.188 + l4_addr_t desc_vaddr,
2.189 + l4re_dma_space_dma_addr_t desc_paddr)
2.190 +{
2.191 + return static_cast<Dma_jz4780_channel *>(dma_channel)->transfer(source,
2.192 + destination, count, source_increment, destination_increment, source_width,
2.193 + destination_width, transfer_unit_size, type, desc_vaddr, desc_paddr);
2.194 +}
2.195 +
2.196 unsigned int jz4780_dma_wait(void *dma_channel)
2.197 {
2.198 return static_cast<Dma_jz4780_channel *>(dma_channel)->wait();
3.1 --- a/pkg/devices/lib/spi/include/spi-jz4780.h Thu Nov 09 18:40:31 2023 +0100
3.2 +++ b/pkg/devices/lib/spi/include/spi-jz4780.h Fri Nov 10 02:02:11 2023 +0100
3.3 @@ -75,7 +75,9 @@
3.4 /* DMA operations. */
3.5
3.6 uint32_t transfer(l4re_dma_space_dma_addr_t paddr, uint32_t count,
3.7 - uint8_t unit_size, uint8_t char_size);
3.8 + uint8_t unit_size, uint8_t char_size,
3.9 + l4_addr_t desc_vaddr = 0,
3.10 + l4re_dma_space_dma_addr_t desc_paddr = 0);
3.11 };
3.12
3.13 /* SPI peripheral. */
3.14 @@ -116,4 +118,9 @@
3.15 uint32_t jz4780_spi_transfer(void *channel, l4re_dma_space_dma_addr_t paddr,
3.16 uint32_t count, uint8_t unit_size, uint8_t char_size);
3.17
3.18 +uint32_t jz4780_spi_transfer_descriptor(void *channel, l4re_dma_space_dma_addr_t paddr,
3.19 + uint32_t count, uint8_t unit_size,
3.20 + uint8_t char_size, l4_addr_t desc_vaddr,
3.21 + l4re_dma_space_dma_addr_t desc_paddr);
3.22 +
3.23 EXTERN_C_END
4.1 --- a/pkg/devices/lib/spi/src/jz4780.cc Thu Nov 09 18:40:31 2023 +0100
4.2 +++ b/pkg/devices/lib/spi/src/jz4780.cc Fri Nov 10 02:02:11 2023 +0100
4.3 @@ -345,7 +345,9 @@
4.4 uint32_t
4.5 Spi_jz4780_channel::transfer(l4re_dma_space_dma_addr_t paddr,
4.6 uint32_t count, uint8_t unit_size,
4.7 - uint8_t char_size)
4.8 + uint8_t char_size,
4.9 + l4_addr_t desc_vaddr,
4.10 + l4re_dma_space_dma_addr_t desc_paddr)
4.11 {
4.12 configure_transfer(char_size);
4.13
4.14 @@ -354,12 +356,18 @@
4.15 uint32_t to_transfer = _dma->transfer(paddr, _spi_start + Ssi_data,
4.16 unit_count, true, false,
4.17 unit_size, unit_size, unit_size,
4.18 - _request_type);
4.19 + _request_type, desc_vaddr, desc_paddr);
4.20 +
4.21 + /* Wait if not using a descriptor, which could be causing an endless,
4.22 + repeating transfer. */
4.23
4.24 - if (to_transfer)
4.25 + if (to_transfer && !desc_vaddr)
4.26 + {
4.27 transferred = to_transfer ? (unit_count - _dma->wait()) * unit_size : 0;
4.28 -
4.29 - wait_busy();
4.30 + wait_busy();
4.31 + }
4.32 + else
4.33 + transferred = to_transfer;
4.34
4.35 return transferred;
4.36 }
4.37 @@ -440,3 +448,12 @@
4.38 return static_cast<Spi_jz4780_channel *>(channel)->transfer(paddr, count,
4.39 unit_size, char_size);
4.40 }
4.41 +
4.42 +uint32_t jz4780_spi_transfer_descriptor(void *channel, l4re_dma_space_dma_addr_t paddr,
4.43 + uint32_t count, uint8_t unit_size,
4.44 + uint8_t char_size, l4_addr_t desc_vaddr,
4.45 + l4re_dma_space_dma_addr_t desc_paddr)
4.46 +{
4.47 + return static_cast<Spi_jz4780_channel *>(channel)->transfer(paddr, count,
4.48 + unit_size, char_size, desc_vaddr, desc_paddr);
4.49 +}
5.1 --- a/pkg/landfall-examples/hw_info/common.h Thu Nov 09 18:40:31 2023 +0100
5.2 +++ b/pkg/landfall-examples/hw_info/common.h Fri Nov 10 02:02:11 2023 +0100
5.3 @@ -188,7 +188,8 @@
5.4 uint8_t unit_size, uint8_t char_size);
5.5
5.6 uint32_t spi_transfer(void *channel, l4re_dma_space_dma_addr_t paddr,
5.7 - uint32_t count, uint8_t unit_size, uint8_t char_size);
5.8 + uint32_t count, uint8_t unit_size, uint8_t char_size,
5.9 + l4_addr_t desc_vaddr, l4re_dma_space_dma_addr_t desc_paddr);
5.10
5.11
5.12
6.1 --- a/pkg/landfall-examples/hw_info/hw_info.c Thu Nov 09 18:40:31 2023 +0100
6.2 +++ b/pkg/landfall-examples/hw_info/hw_info.c Fri Nov 10 02:02:11 2023 +0100
6.3 @@ -1127,7 +1127,7 @@
6.4 static void spi_transfer_data(void)
6.5 {
6.6 void *channel = get_channel(num_spi_channels, spi_channels, NULL);
6.7 - struct dma_region *region;
6.8 + struct dma_region *region, *desc_region;
6.9 unsigned int char_size, unit_size;
6.10 uint32_t count, transferred;
6.11
6.12 @@ -1148,7 +1148,11 @@
6.13 if (!read_number("Character size", &char_size))
6.14 return;
6.15
6.16 - transferred = spi_transfer(channel, region->paddr, count, unit_size, char_size);
6.17 + desc_region = _get_dma_region();
6.18 +
6.19 + transferred = spi_transfer(channel, region->paddr, count, unit_size, char_size,
6.20 + desc_region != NULL ? desc_region->vaddr : 0,
6.21 + desc_region != NULL ? desc_region->paddr : 0);
6.22
6.23 printf("Transferred: %d\n", transferred);
6.24 }
7.1 --- a/pkg/landfall-examples/hw_info/jz4780.c Thu Nov 09 18:40:31 2023 +0100
7.2 +++ b/pkg/landfall-examples/hw_info/jz4780.c Fri Nov 10 02:02:11 2023 +0100
7.3 @@ -379,13 +379,15 @@
7.4 }
7.5
7.6 uint32_t spi_transfer(void *channel, l4re_dma_space_dma_addr_t paddr,
7.7 - uint32_t count, uint8_t unit_size, uint8_t char_size)
7.8 + uint32_t count, uint8_t unit_size, uint8_t char_size,
7.9 + l4_addr_t desc_vaddr, l4re_dma_space_dma_addr_t desc_paddr)
7.10 {
7.11 /* Transfer is not supported by the common interface. */
7.12
7.13 void *ch = spi_hybrid_get_raw_channel(channel);
7.14
7.15 - return jz4780_spi_transfer(ch, paddr, count, unit_size, char_size);
7.16 + return jz4780_spi_transfer_descriptor(ch, paddr, count, unit_size, char_size,
7.17 + desc_vaddr, desc_paddr);
7.18 }
7.19
7.20
8.1 --- a/pkg/landfall-examples/hw_info/x1600.c Thu Nov 09 18:40:31 2023 +0100
8.2 +++ b/pkg/landfall-examples/hw_info/x1600.c Fri Nov 10 02:02:11 2023 +0100
8.3 @@ -382,12 +382,15 @@
8.4 }
8.5
8.6 uint32_t spi_transfer(void *channel, l4re_dma_space_dma_addr_t paddr,
8.7 - uint32_t count, uint8_t unit_size, uint8_t char_size)
8.8 + uint32_t count, uint8_t unit_size, uint8_t char_size,
8.9 + l4_addr_t desc_vaddr, l4re_dma_space_dma_addr_t desc_paddr)
8.10 {
8.11 /* NOTE: Not yet supported. */
8.12
8.13 (void) channel; (void) paddr; (void) count; (void) unit_size; (void) char_size;
8.14 - // return x1600_spi_transfer(channel, paddr, count, unit_size, char_size);
8.15 + (void) desc_vaddr; (void) desc_paddr;
8.16 + // return x1600_spi_transfer(channel, paddr, count, unit_size, char_size,
8.17 + // desc_vaddr, desc_paddr);
8.18 return 0;
8.19 }
8.20