1.1 --- a/pkg/devices/lib/spi/src/jz4780.cc Mon Nov 13 01:20:09 2023 +0100
1.2 +++ b/pkg/devices/lib/spi/src/jz4780.cc Tue Nov 14 00:02:42 2023 +0100
1.3 @@ -19,8 +19,9 @@
1.4 * Boston, MA 02110-1301, USA
1.5 */
1.6
1.7 +#include <l4/devices/byteorder.h>
1.8 +#include <l4/devices/dma.h>
1.9 #include <l4/devices/spi-jz4780.h>
1.10 -#include <l4/devices/dma.h>
1.11 #include <l4/sys/err.h>
1.12 #include <string.h>
1.13
1.14 @@ -288,29 +289,33 @@
1.15 uint32_t
1.16 Spi_jz4780_channel::send(uint32_t bytes, const uint8_t data[])
1.17 {
1.18 - return send_units(bytes, data, 1, 8);
1.19 + return send_units(bytes, data, 1, 8, false);
1.20 }
1.21
1.22 /* Transfer the given number of bytes from a buffer together with control values. */
1.23
1.24 uint32_t
1.25 Spi_jz4780_channel::send_dc(uint32_t bytes, const uint8_t data[],
1.26 - const int dc[])
1.27 + const int dc[], uint8_t char_size, bool big_endian)
1.28 {
1.29 - configure_transfer(8);
1.30 + configure_transfer(char_size);
1.31
1.32 - uint32_t transferred;
1.33 + uint32_t transferred, char_unit;
1.34 + uint8_t char_unit_size = ((char_size ? char_size - 1 : 0) / 8) + 1;
1.35 + uint32_t char_mask = (1 << char_size) - 1;
1.36
1.37 - for (transferred = 0; transferred < bytes; transferred++)
1.38 + for (transferred = 0, char_unit = 0; transferred < bytes;
1.39 + transferred += char_unit_size, char_unit++)
1.40 {
1.41 + uint32_t value = get_stored_value(&data[transferred], char_unit_size, big_endian);
1.42 +
1.43 /* Relocate the data/command level to bit 16. */
1.44
1.45 - uint32_t command = dc[transferred] ? Ssi_data_gpc_set : Ssi_data_gpc_unset;
1.46 - uint32_t value = data[transferred];
1.47 + uint32_t command = dc[char_unit] ? Ssi_data_gpc_set : Ssi_data_gpc_unset;
1.48
1.49 /* Combine the character with the data/command bit. */
1.50
1.51 - _regs[Ssi_data] = value | command;
1.52 + _regs[Ssi_data] = (value & char_mask) | command;
1.53 }
1.54
1.55 wait_busy();
1.56 @@ -324,7 +329,8 @@
1.57
1.58 uint32_t
1.59 Spi_jz4780_channel::send_units(uint32_t bytes, const uint8_t data[],
1.60 - uint8_t unit_size, uint8_t char_size)
1.61 + uint8_t unit_size, uint8_t char_size,
1.62 + bool big_endian)
1.63 {
1.64 configure_transfer(char_size);
1.65
1.66 @@ -333,10 +339,7 @@
1.67
1.68 for (transferred = 0; transferred < bytes; transferred += unit_size)
1.69 {
1.70 - uint32_t value = 0;
1.71 -
1.72 - for (uint8_t byte = 0; byte < unit_size; byte++)
1.73 - value = (value << 8) | data[transferred + byte];
1.74 + uint32_t value = get_stored_value(&data[transferred], unit_size, big_endian);
1.75
1.76 /* Relocate any command bit to bit 16 for byte characters. */
1.77
1.78 @@ -345,8 +348,7 @@
1.79
1.80 /* Combine the character portion of the unit with the command. */
1.81
1.82 - value = (value & char_mask) | command;
1.83 - _regs[Ssi_data] = value;
1.84 + _regs[Ssi_data] = (value & char_mask) | command;
1.85 }
1.86
1.87 wait_busy();
1.88 @@ -358,12 +360,23 @@
1.89 unit size in bytes and character size in bits. */
1.90
1.91 uint32_t
1.92 -Spi_jz4780_channel::transfer(l4re_dma_space_dma_addr_t paddr,
1.93 +Spi_jz4780_channel::transfer(l4_addr_t vaddr,
1.94 + l4re_dma_space_dma_addr_t paddr,
1.95 uint32_t count, uint8_t unit_size,
1.96 uint8_t char_size,
1.97 l4_addr_t desc_vaddr,
1.98 l4re_dma_space_dma_addr_t desc_paddr)
1.99 {
1.100 + /* Employ a non-DMA transfer if no usable physical address is provided.
1.101 + Assume little endian byte ordering in line with the native value
1.102 + representation. */
1.103 +
1.104 + if (!paddr)
1.105 + return send_units(count, (const uint8_t *) vaddr, unit_size, char_size,
1.106 + false);
1.107 +
1.108 + /* Configure and initiate a DMA transfer with optional descriptor. */
1.109 +
1.110 configure_transfer(char_size);
1.111
1.112 uint32_t transferred = 0;
1.113 @@ -444,31 +457,34 @@
1.114 }
1.115
1.116 uint32_t jz4780_spi_send_dc(void *channel, uint32_t bytes, const uint8_t data[],
1.117 - const int dc[])
1.118 + const int dc[], uint8_t char_size, int big_endian)
1.119 {
1.120 - return static_cast<Spi_jz4780_channel *>(channel)->send_dc(bytes, data, dc);
1.121 + return static_cast<Spi_jz4780_channel *>(channel)->send_dc(bytes, data, dc,
1.122 + char_size, big_endian);
1.123 }
1.124
1.125 uint32_t jz4780_spi_send_units(void *channel, uint32_t bytes, const uint8_t data[],
1.126 - uint8_t unit_size, uint8_t char_size)
1.127 + uint8_t unit_size, uint8_t char_size, int big_endian)
1.128 {
1.129 return static_cast<Spi_jz4780_channel *>(channel)->send_units(bytes, data,
1.130 - unit_size, char_size);
1.131 + unit_size, char_size, big_endian);
1.132 }
1.133
1.134 -uint32_t jz4780_spi_transfer(void *channel, l4re_dma_space_dma_addr_t paddr,
1.135 +uint32_t jz4780_spi_transfer(void *channel, l4_addr_t vaddr,
1.136 + l4re_dma_space_dma_addr_t paddr,
1.137 uint32_t count, uint8_t unit_size,
1.138 uint8_t char_size)
1.139 {
1.140 - return static_cast<Spi_jz4780_channel *>(channel)->transfer(paddr, count,
1.141 - unit_size, char_size);
1.142 + return static_cast<Spi_jz4780_channel *>(channel)->transfer(vaddr, paddr,
1.143 + count, unit_size, char_size);
1.144 }
1.145
1.146 -uint32_t jz4780_spi_transfer_descriptor(void *channel, l4re_dma_space_dma_addr_t paddr,
1.147 +uint32_t jz4780_spi_transfer_descriptor(void *channel, l4_addr_t vaddr,
1.148 + l4re_dma_space_dma_addr_t paddr,
1.149 uint32_t count, uint8_t unit_size,
1.150 uint8_t char_size, l4_addr_t desc_vaddr,
1.151 l4re_dma_space_dma_addr_t desc_paddr)
1.152 {
1.153 - return static_cast<Spi_jz4780_channel *>(channel)->transfer(paddr, count,
1.154 - unit_size, char_size, desc_vaddr, desc_paddr);
1.155 + return static_cast<Spi_jz4780_channel *>(channel)->transfer(vaddr, paddr,
1.156 + count, unit_size, char_size, desc_vaddr, desc_paddr);
1.157 }