1.1 Binary file conf/landfall-examples/P8021407-crop-240x240.data has changed
2.1 --- a/conf/landfall-examples/mips-jz4780-info.io Fri Nov 03 19:58:11 2023 +0100 2.2 +++ b/conf/landfall-examples/mips-jz4780-info.io Tue Nov 07 19:20:32 2023 +0100 2.3 @@ -10,6 +10,7 @@ 2.4 DMA = wrap(hw:match("jz4780-dma")); 2.5 GPIO = wrap(hw:match("jz4780-gpio")); 2.6 I2C = wrap(hw:match("jz4780-i2c")); 2.7 + SSI = wrap(hw:match("jz4780-ssi")); 2.8 } 2.9 2.10 Io.add_vbus("common", bus)
3.1 --- a/conf/landfall-examples/mips-jz4780-info.list Fri Nov 03 19:58:11 2023 +0100 3.2 +++ b/conf/landfall-examples/mips-jz4780-info.list Tue Nov 07 19:20:32 2023 +0100 3.3 @@ -13,3 +13,4 @@ 3.4 module ned 3.5 module ex_jz4780_info 3.6 module piano-3.raw 3.7 +module P8021407-crop-240x240.data
4.1 --- a/conf/landfall-examples/mips-x1600-info.io Fri Nov 03 19:58:11 2023 +0100 4.2 +++ b/conf/landfall-examples/mips-x1600-info.io Tue Nov 07 19:20:32 2023 +0100 4.3 @@ -10,6 +10,7 @@ 4.4 DMA = wrap(hw:match("x1600-dma")); 4.5 GPIO = wrap(hw:match("x1600-gpio")); 4.6 I2C = wrap(hw:match("x1600-i2c")); 4.7 + SSI = wrap(hw:match("x1600-ssi")); 4.8 } 4.9 4.10 Io.add_vbus("common", bus)
5.1 --- a/pkg/devices/lib/Makefile Fri Nov 03 19:58:11 2023 +0100 5.2 +++ b/pkg/devices/lib/Makefile Tue Nov 07 19:20:32 2023 +0100 5.3 @@ -5,14 +5,14 @@ 5.4 5.5 include $(L4DIR)/mk/subdir.mk 5.6 5.7 -aic: cpm gpio 5.8 +aic: cpm dma gpio 5.9 cpm: common 5.10 dma: common 5.11 gpio: common 5.12 hdmi: panel 5.13 -i2c: cpm gpio 5.14 +i2c: cpm dma gpio 5.15 keypad: common 5.16 lcd: common 5.17 panel: lcd 5.18 pwm: common 5.19 -spi: gpio 5.20 +spi: cpm dma gpio
6.1 --- a/pkg/devices/lib/aic/include/aic-x1600.h Fri Nov 03 19:58:11 2023 +0100 6.2 +++ b/pkg/devices/lib/aic/include/aic-x1600.h Tue Nov 07 19:20:32 2023 +0100 6.3 @@ -44,13 +44,6 @@ 6.4 Cpm_x1600_chip *_cpm; 6.5 Dma_x1600_channel *_dma; 6.6 6.7 - /* Buffer management. */ 6.8 - 6.9 - unsigned int _size = 0; 6.10 - l4_addr_t _vaddr = 0; 6.11 - l4re_dma_space_dma_addr_t _paddr = 0; 6.12 - l4_cap_idx_t _mem = L4_INVALID_CAP; 6.13 - 6.14 public: 6.15 explicit Aic_x1600_channel(l4_addr_t aic_start, l4_addr_t start, 6.16 enum Clock_identifiers clock_rx, 6.17 @@ -58,8 +51,8 @@ 6.18 Cpm_x1600_chip *cpm, 6.19 Dma_x1600_channel *dma); 6.20 6.21 - long get_buffer(uint32_t count, l4_addr_t *addr); 6.22 - uint32_t transfer(uint32_t count, uint32_t sample_rate, uint8_t sample_size); 6.23 + uint32_t transfer(l4re_dma_space_dma_addr_t paddr, uint32_t count, 6.24 + uint32_t sample_rate, uint8_t sample_size); 6.25 6.26 private: 6.27 void disable(); 6.28 @@ -100,8 +93,8 @@ 6.29 6.30 void *x1600_aic_get_channel(void *aic, uint8_t channel, void *dma); 6.31 6.32 -long x1600_aic_get_buffer(void *channel, uint32_t count, l4_addr_t *addr); 6.33 - 6.34 -uint32_t x1600_aic_transfer(void *channel, uint32_t count, uint32_t sample_rate, uint8_t sample_size); 6.35 +uint32_t x1600_aic_transfer(void *channel, l4re_dma_space_dma_addr_t paddr, 6.36 + uint32_t count, uint32_t sample_rate, 6.37 + uint8_t sample_size); 6.38 6.39 EXTERN_C_END
7.1 --- a/pkg/devices/lib/aic/src/x1600.cc Fri Nov 03 19:58:11 2023 +0100 7.2 +++ b/pkg/devices/lib/aic/src/x1600.cc Tue Nov 07 19:20:32 2023 +0100 7.3 @@ -312,32 +312,13 @@ 7.4 } 7.5 } 7.6 7.7 -/* Obtain a DMA-accessible buffer for sample transfers. */ 7.8 - 7.9 -long 7.10 -Aic_x1600_channel::get_buffer(uint32_t count, l4_addr_t *addr) 7.11 -{ 7.12 - long err = get_dma_region(count, 8, &_vaddr, &_paddr, &_mem); 7.13 - 7.14 - if (err) 7.15 - return err; 7.16 - 7.17 - // Set the region size as the requested size, not any allocated size. 7.18 - 7.19 - _size = count; 7.20 - *addr = _vaddr; 7.21 - return L4_EOK; 7.22 -} 7.23 - 7.24 /* Transfer a sample using the given byte count (total sample size), sample rate 7.25 (or frequency), sample unit size (or resolution, width). */ 7.26 7.27 uint32_t 7.28 -Aic_x1600_channel::transfer(uint32_t count, uint32_t sample_rate, uint8_t sample_size) 7.29 +Aic_x1600_channel::transfer(l4re_dma_space_dma_addr_t paddr, uint32_t count, 7.30 + uint32_t sample_rate, uint8_t sample_size) 7.31 { 7.32 - if (count > _size) 7.33 - return 0; 7.34 - 7.35 /* To play a sample: 7.36 7.37 - Configure the sample size using the Aic_output_size settings in Aic_control 7.38 @@ -375,7 +356,7 @@ 7.39 7.40 uint32_t sample_unit = (sample_size == 8) ? 1 : (sample_size == 16) ? 2 : 4; 7.41 uint32_t unit_count = count / sample_unit; 7.42 - uint32_t to_transfer = _dma->transfer(_paddr, 7.43 + uint32_t to_transfer = _dma->transfer(paddr, 7.44 _aic_start + Aic_fifo_data, 7.45 unit_count, 7.46 true, 7.47 @@ -436,12 +417,10 @@ 7.48 static_cast<Dma_x1600_channel *>(dma)); 7.49 } 7.50 7.51 -long x1600_aic_get_buffer(void *channel, uint32_t count, l4_addr_t *addr) 7.52 +uint32_t x1600_aic_transfer(void *channel, l4re_dma_space_dma_addr_t paddr, 7.53 + uint32_t count, uint32_t sample_rate, 7.54 + uint8_t sample_size) 7.55 { 7.56 - return static_cast<Aic_x1600_channel *>(channel)->get_buffer(count, addr); 7.57 + return static_cast<Aic_x1600_channel *>(channel)->transfer(paddr, count, 7.58 + sample_rate, sample_size); 7.59 } 7.60 - 7.61 -uint32_t x1600_aic_transfer(void *channel, uint32_t count, uint32_t sample_rate, uint8_t sample_size) 7.62 -{ 7.63 - return static_cast<Aic_x1600_channel *>(channel)->transfer(count, sample_rate, sample_size); 7.64 -}
8.1 --- a/pkg/devices/lib/spi/include/spi-gpio.h Fri Nov 03 19:58:11 2023 +0100 8.2 +++ b/pkg/devices/lib/spi/include/spi-gpio.h Tue Nov 07 19:20:32 2023 +0100 8.3 @@ -19,11 +19,11 @@ 8.4 * Boston, MA 02110-1301, USA 8.5 */ 8.6 8.7 +#pragma once 8.8 + 8.9 #include <l4/devices/gpio.h> 8.10 #include <stdint.h> 8.11 8.12 -#pragma once 8.13 - 8.14 8.15 8.16 #ifdef __cplusplus 8.17 @@ -38,15 +38,13 @@ 8.18 int _data_pin; 8.19 Hw::Gpio_chip *_enable_device; 8.20 int _enable_pin; 8.21 - uint32_t _frequency; 8.22 + uint64_t _frequency; 8.23 8.24 public: 8.25 - /* Associate the device with a particular memory region. */ 8.26 - 8.27 explicit Spi_gpio(Hw::Gpio_chip *clock_device, int clock_pin, 8.28 Hw::Gpio_chip *data_device, int data_pin, 8.29 Hw::Gpio_chip *enable_device, int enable_pin, 8.30 - uint32_t frequency = 0); 8.31 + uint64_t frequency = 0); 8.32 8.33 void send(int bytes, const uint8_t data[]); 8.34 }; 8.35 @@ -62,7 +60,7 @@ 8.36 void *spi_gpio_get_channel(void *clock_chip, int clock_pin, 8.37 void *data_chip, int data_pin, 8.38 void *enable_chip, int enable_pin, 8.39 - uint32_t frequency); 8.40 + uint64_t frequency); 8.41 8.42 void spi_gpio_send(void *channel, int bytes, const uint8_t data[]); 8.43
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/pkg/devices/lib/spi/include/spi-jz4780.h Tue Nov 07 19:20:32 2023 +0100 9.3 @@ -0,0 +1,105 @@ 9.4 +/* 9.5 + * Perform SPI communication using the JZ4780 SPI peripheral. 9.6 + * 9.7 + * Copyright (C) 2023 Paul Boddie <paul@boddie.org.uk> 9.8 + * 9.9 + * This program is free software; you can redistribute it and/or 9.10 + * modify it under the terms of the GNU General Public License as 9.11 + * published by the Free Software Foundation; either version 2 of 9.12 + * the License, or (at your option) any later version. 9.13 + * 9.14 + * This program is distributed in the hope that it will be useful, 9.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 9.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9.17 + * GNU General Public License for more details. 9.18 + * 9.19 + * You should have received a copy of the GNU General Public License 9.20 + * along with this program; if not, write to the Free Software 9.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 9.22 + * Boston, MA 02110-1301, USA 9.23 + */ 9.24 + 9.25 +#pragma once 9.26 + 9.27 +#include <l4/re/c/dma_space.h> 9.28 +#include <l4/sys/types.h> 9.29 +#include <stdint.h> 9.30 + 9.31 + 9.32 + 9.33 +#ifdef __cplusplus 9.34 + 9.35 +#include <l4/devices/cpm-jz4780.h> 9.36 +#include <l4/devices/dma-jz4780.h> 9.37 +#include <l4/devices/hw_mmio_register_block.h> 9.38 + 9.39 +/* SPI peripheral channel. */ 9.40 + 9.41 +class Spi_jz4780_channel 9.42 +{ 9.43 + Hw::Register_block<32> _regs; 9.44 + 9.45 + /* Initialisation parameters. */ 9.46 + 9.47 + l4_addr_t _spi_start; 9.48 + enum Clock_identifiers _clock; 9.49 + Cpm_jz4780_chip *_cpm; 9.50 + Dma_jz4780_channel *_dma; 9.51 + enum Dma_jz4780_request_type _request_type; 9.52 + uint64_t _frequency; 9.53 + 9.54 + void configure_transfer(uint8_t char_size); 9.55 + 9.56 +public: 9.57 + explicit Spi_jz4780_channel(l4_addr_t spi_start, l4_addr_t start, 9.58 + enum Clock_identifiers clock, 9.59 + Cpm_jz4780_chip *cpm, 9.60 + Dma_jz4780_channel *dma, 9.61 + enum Dma_jz4780_request_type request_type, 9.62 + uint64_t frequency); 9.63 + 9.64 + /* DMA operations. */ 9.65 + 9.66 + uint32_t transfer(l4re_dma_space_dma_addr_t paddr, uint32_t count, 9.67 + uint8_t unit_size, uint8_t char_size); 9.68 + 9.69 + /* Convenience operations. */ 9.70 + 9.71 + uint32_t send(uint32_t bytes, const uint8_t data[], uint8_t unit_size, 9.72 + uint8_t char_size); 9.73 +}; 9.74 + 9.75 +/* SPI peripheral. */ 9.76 + 9.77 +class Spi_jz4780_chip 9.78 +{ 9.79 +private: 9.80 + l4_addr_t _spi_start, _start, _end; 9.81 + Cpm_jz4780_chip *_cpm; 9.82 + 9.83 +public: 9.84 + explicit Spi_jz4780_chip(l4_addr_t spi_start, l4_addr_t start, l4_addr_t end, Cpm_jz4780_chip *cpm); 9.85 + 9.86 + Spi_jz4780_channel *get_channel(uint8_t channel, Dma_jz4780_channel *dma, uint64_t frequency); 9.87 +}; 9.88 + 9.89 +#endif /* __cplusplus */ 9.90 + 9.91 + 9.92 + 9.93 +/* C language interface. */ 9.94 + 9.95 +EXTERN_C_BEGIN 9.96 + 9.97 +void *jz4780_spi_init(l4_addr_t spi_start, l4_addr_t start, l4_addr_t end, 9.98 + void *cpm); 9.99 + 9.100 +void *jz4780_spi_get_channel(void *spi, uint8_t channel, void *dma, uint64_t frequency); 9.101 + 9.102 +uint32_t jz4780_spi_send(void *channel, uint32_t bytes, const uint8_t data[], 9.103 + uint8_t unit_size, uint8_t char_size); 9.104 + 9.105 +uint32_t jz4780_spi_transfer(void *channel, l4re_dma_space_dma_addr_t paddr, 9.106 + uint32_t count, uint8_t unit_size, uint8_t char_size); 9.107 + 9.108 +EXTERN_C_END
10.1 --- a/pkg/devices/lib/spi/src/Makefile Fri Nov 03 19:58:11 2023 +0100 10.2 +++ b/pkg/devices/lib/spi/src/Makefile Tue Nov 07 19:20:32 2023 +0100 10.3 @@ -4,10 +4,10 @@ 10.4 TARGET = libspi.o.a libspi.o.so 10.5 PC_FILENAME := libdrivers-spi 10.6 10.7 -SRC_CC := gpio.cc 10.8 +SRC_CC := gpio.cc jz4780.cc 10.9 10.10 PRIVATE_INCDIR += $(PKGDIR)/lib/spi/include 10.11 10.12 -REQUIRES_LIBS := l4re_c l4re_c-util libdrivers-common libdrivers-gpio 10.13 +REQUIRES_LIBS := l4re_c l4re_c-util libdrivers-common libdrivers-cpm libdrivers-dma libdrivers-gpio 10.14 10.15 include $(L4DIR)/mk/lib.mk
11.1 --- a/pkg/devices/lib/spi/src/gpio.cc Fri Nov 03 19:58:11 2023 +0100 11.2 +++ b/pkg/devices/lib/spi/src/gpio.cc Tue Nov 07 19:20:32 2023 +0100 11.3 @@ -27,7 +27,7 @@ 11.4 Spi_gpio::Spi_gpio(Hw::Gpio_chip *clock_device, int clock_pin, 11.5 Hw::Gpio_chip *data_device, int data_pin, 11.6 Hw::Gpio_chip *enable_device, int enable_pin, 11.7 - uint32_t frequency) 11.8 + uint64_t frequency) 11.9 : _clock_device(clock_device), 11.10 _clock_pin(clock_pin), 11.11 _data_device(data_device), 11.12 @@ -41,7 +41,7 @@ 11.13 _enable_device->setup(_enable_pin, Hw::Gpio_chip::Output, 1); 11.14 } 11.15 11.16 -/* Send a SPI command. */ 11.17 +/* Send a byte sequence. */ 11.18 11.19 void Spi_gpio::send(int bytes, const uint8_t data[]) 11.20 { 11.21 @@ -102,7 +102,7 @@ 11.22 void *spi_gpio_get_channel(void *clock_chip, int clock_pin, 11.23 void *data_chip, int data_pin, 11.24 void *enable_chip, int enable_pin, 11.25 - uint32_t frequency) 11.26 + uint64_t frequency) 11.27 { 11.28 return (void *) new Spi_gpio(reinterpret_cast<Hw::Gpio_chip *>(clock_chip), clock_pin, 11.29 reinterpret_cast<Hw::Gpio_chip *>(data_chip), data_pin,
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/pkg/devices/lib/spi/src/jz4780.cc Tue Nov 07 19:20:32 2023 +0100 12.3 @@ -0,0 +1,387 @@ 12.4 +/* 12.5 + * Perform SPI communication using the JZ4780 SPI peripheral. 12.6 + * 12.7 + * Copyright (C) 2023 Paul Boddie <paul@boddie.org.uk> 12.8 + * 12.9 + * This program is free software; you can redistribute it and/or 12.10 + * modify it under the terms of the GNU General Public License as 12.11 + * published by the Free Software Foundation; either version 2 of 12.12 + * the License, or (at your option) any later version. 12.13 + * 12.14 + * This program is distributed in the hope that it will be useful, 12.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 12.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12.17 + * GNU General Public License for more details. 12.18 + * 12.19 + * You should have received a copy of the GNU General Public License 12.20 + * along with this program; if not, write to the Free Software 12.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 12.22 + * Boston, MA 02110-1301, USA 12.23 + */ 12.24 + 12.25 +#include <l4/devices/spi-jz4780.h> 12.26 +#include <l4/devices/dma.h> 12.27 +#include <l4/sys/err.h> 12.28 +#include <string.h> 12.29 + 12.30 + 12.31 + 12.32 +/* Register definitions. */ 12.33 + 12.34 +enum Regs 12.35 +{ 12.36 + Ssi_data = 0x00, // SSIDR 12.37 + Ssi_control0 = 0x04, // SSICR0 12.38 + Ssi_control1 = 0x08, // SSICR1 12.39 + Ssi_status = 0x0c, // SSISR 12.40 + Ssi_interval_time = 0x10, // SSIITR 12.41 + Ssi_char_per_frame = 0x14, // SSIICR 12.42 + Ssi_clock = 0x18, // SSICGR 12.43 + Ssi_recv_counter = 0x1c, // SSIRCNT 12.44 + 12.45 + /* Register block offset. */ 12.46 + 12.47 + Ssi_block_offset = 0x1000, 12.48 +}; 12.49 + 12.50 +enum Ssi_data_bits : unsigned 12.51 +{ 12.52 + Ssi_data_gpc = 0x1000, 12.53 +}; 12.54 + 12.55 +enum Ssi_control0_bits : unsigned 12.56 +{ 12.57 + Ssi_trans_endian_mask = 0xc0000, 12.58 + Ssi_trans_endian_msbyte_msbit = 0x00000, 12.59 + Ssi_trans_endian_msbyte_lsbit = 0x40000, 12.60 + Ssi_trans_endian_lsbyte_lsbit = 0x80000, 12.61 + Ssi_trans_endian_lsbyte_msbit = 0xc0000, 12.62 + 12.63 + Ssi_recv_endian_mask = 0x30000, 12.64 + Ssi_recv_endian_msbyte_msbit = 0x00000, 12.65 + Ssi_recv_endian_msbyte_lsbit = 0x10000, 12.66 + Ssi_recv_endian_lsbyte_lsbit = 0x20000, 12.67 + Ssi_recv_endian_lsbyte_msbit = 0x30000, 12.68 + 12.69 + Ssi_enable = 0x08000, 12.70 + Ssi_enable_trans_half_empty = 0x04000, 12.71 + Ssi_enable_recv_half_full = 0x02000, 12.72 + Ssi_enable_trans_error = 0x01000, 12.73 + Ssi_enable_recv_error = 0x00800, 12.74 + Ssi_loop = 0x00400, 12.75 + Ssi_recv_finish_control = 0x00200, 12.76 + Ssi_recv_finished = 0x00100, 12.77 + Ssi_enable_auto_clear_underrun = 0x00080, 12.78 + Ssi_select_pin_is_ce2 = 0x00040, 12.79 + Ssi_use_recv_count = 0x00010, 12.80 + Ssi_old_fifo_empty_mode = 0x00008, 12.81 + Ssi_trans_flush = 0x00004, 12.82 + Ssi_recv_flush = 0x00002, 12.83 + Ssi_disable_recv = 0x00001, 12.84 +}; 12.85 + 12.86 +enum Ssi_control1_bits : unsigned 12.87 +{ 12.88 + Ssi_active_mask = 0xc0000000, 12.89 + Ssi_active_ce_low = 0x00000000, 12.90 + Ssi_active_ce_high = 0x40000000, 12.91 + Ssi_active_ce2_low = 0x00000000, 12.92 + Ssi_active_ce2_high = 0x80000000, 12.93 + 12.94 + Ssi_clock_start_delay_mask = 0x30000000, 12.95 + Ssi_clock_start_delay_default = 0x00000000, 12.96 + Ssi_clock_start_delay_plus_1 = 0x10000000, 12.97 + Ssi_clock_start_delay_plus_2 = 0x20000000, 12.98 + Ssi_clock_start_delay_plus_3 = 0x30000000, 12.99 + 12.100 + Ssi_clock_stop_delay_mask = 0x0c000000, 12.101 + Ssi_clock_stop_delay_default = 0x00000000, 12.102 + Ssi_clock_stop_delay_plus_1 = 0x04000000, 12.103 + Ssi_clock_stop_delay_plus_2 = 0x08000000, 12.104 + Ssi_clock_stop_delay_plus_3 = 0x0c000000, 12.105 + 12.106 + Ssi_interval_assert_ce_or_ce2 = 0x01000000, 12.107 + Ssi_trans_empty_unfinished = 0x00800000, 12.108 + 12.109 + Ssi_format_mask = 0x00300000, 12.110 + Ssi_format_spi = 0x00000000, 12.111 + Ssi_format_ssp = 0x00100000, 12.112 + Ssi_format_microwire1 = 0x00200000, 12.113 + Ssi_format_microwire2 = 0x00300000, 12.114 + 12.115 + Ssi_trans_threshold_mask = 0x000f0000, 12.116 + Ssi_command_length_mask = 0x0000f000, 12.117 + Ssi_recv_threshold_mask = 0x00000f00, 12.118 + Ssi_char_length_mask = 0x000000f8, 12.119 + 12.120 + Spi_clock_assert_sample = 0x00000000, // phase #0 12.121 + Spi_clock_assert_drive = 0x00000002, // phase #1 12.122 + Spi_clock_idle_low_level = 0x00000000, // polarity #0 12.123 + Spi_clock_idle_high_level = 0x00000001, // polarity #1 12.124 +}; 12.125 + 12.126 +enum Ssi_control1_shifts : unsigned 12.127 +{ 12.128 + Ssi_trans_threshold_shift = 16, 12.129 + Ssi_command_length_shift = 12, 12.130 + Ssi_recv_threshold_shift = 8, 12.131 + Ssi_char_length_shift = 3, 12.132 +}; 12.133 + 12.134 +enum Ssi_control1_limits : unsigned 12.135 +{ 12.136 + Ssi_trans_threshold_limit = 15, 12.137 + Ssi_command_length_limit = 15, 12.138 + Ssi_recv_threshold_limit = 15, 12.139 + Ssi_char_length_limit = 30, 12.140 +}; 12.141 + 12.142 +enum Ssi_status_bits : unsigned 12.143 +{ 12.144 + Ssi_trans_char_count_mask = 0x00ff0000, 12.145 + Ssi_recv_char_count_mask = 0x0000ff00, 12.146 + Ssi_trans_ended = 0x00000080, 12.147 + Ssi_trans_busy = 0x00000040, 12.148 + Ssi_trans_fifo_full = 0x00000020, 12.149 + Ssi_recv_fifo_empty = 0x00000010, 12.150 + Ssi_trans_fifo_half_empty = 0x00000008, 12.151 + Ssi_recv_fifo_half_full = 0x00000004, 12.152 + Ssi_trans_underrun = 0x00000002, 12.153 + Ssi_recv_overrun = 0x00000001, 12.154 +}; 12.155 + 12.156 +enum Ssi_status_shifts : unsigned 12.157 +{ 12.158 + Ssi_trans_char_count_shift = 16, 12.159 + Ssi_recv_char_count_shift = 8, 12.160 +}; 12.161 + 12.162 +enum Ssi_status_limits : unsigned 12.163 +{ 12.164 + Ssi_trans_char_count_limit = 0xff, 12.165 + Ssi_recv_char_count_limit = 0xff, 12.166 +}; 12.167 + 12.168 +enum Ssi_interval_time_bits : unsigned 12.169 +{ 12.170 + Ssi_interval_clock_mask = 0x8000, 12.171 + Ssi_interval_clock_bit_clock = 0x0000, 12.172 + Ssi_interval_clock_32k_clock = 0x8000, 12.173 + Ssi_interval_time_mask = 0x3fff, 12.174 +}; 12.175 + 12.176 +enum Ssi_char_per_frame_bits : unsigned 12.177 +{ 12.178 + Ssi_char_per_frame_mask = 0x7, 12.179 +}; 12.180 + 12.181 +enum Ssi_clock_bits : unsigned 12.182 +{ 12.183 + Ssi_clock_frequency_mask = 0xff, 12.184 +}; 12.185 + 12.186 +enum Ssi_recv_counter_bits : unsigned 12.187 +{ 12.188 + Ssi_recv_counter_mask = 0xffff, 12.189 +}; 12.190 + 12.191 + 12.192 + 12.193 +/* Initialise a channel. */ 12.194 + 12.195 +Spi_jz4780_channel::Spi_jz4780_channel(l4_addr_t spi_start, l4_addr_t start, 12.196 + enum Clock_identifiers clock, 12.197 + Cpm_jz4780_chip *cpm, 12.198 + Dma_jz4780_channel *dma, 12.199 + enum Dma_jz4780_request_type request_type, 12.200 + uint64_t frequency) 12.201 +: _spi_start(spi_start), _clock(clock), _cpm(cpm), _dma(dma), 12.202 + _request_type(request_type), _frequency(frequency) 12.203 +{ 12.204 + _regs = new Hw::Mmio_register_block<32>(start); 12.205 + _cpm->start_clock(clock); 12.206 + 12.207 + /* Disable the channel while configuring: send MSB first, big endian wire 12.208 + representation. Disable reception. */ 12.209 + 12.210 + _regs[Ssi_control0] = Ssi_trans_endian_msbyte_msbit | 12.211 + Ssi_select_pin_is_ce2 | 12.212 + Ssi_disable_recv; 12.213 + 12.214 + /* Set default transfer properties. */ 12.215 + 12.216 + configure_transfer(8); 12.217 + 12.218 + /* Select "normal" mode. */ 12.219 + 12.220 + _regs[Ssi_interval_time] = 0; 12.221 + 12.222 + /* Limit the frequency to half that of the device clock. */ 12.223 + 12.224 + if (_frequency >= _cpm->get_frequency(_clock)) 12.225 + _frequency = _cpm->get_frequency(_clock) / 2; 12.226 + 12.227 + /* SSI_CLK = DEV_CLK / (2 * (divider + 1)) */ 12.228 + 12.229 + uint32_t divider = _cpm->get_frequency(_clock) / (_frequency * 2) - 1; 12.230 + 12.231 + _regs[Ssi_clock] = divider < Ssi_clock_frequency_mask ? divider : Ssi_clock_frequency_mask; 12.232 + 12.233 + /* Enable the channel. */ 12.234 + 12.235 + _regs[Ssi_control0] = _regs[Ssi_control0] | Ssi_enable; 12.236 +} 12.237 + 12.238 +/* NOTE: More transfer characteristics should be configurable. */ 12.239 + 12.240 +void Spi_jz4780_channel::configure_transfer(uint8_t char_size) 12.241 +{ 12.242 + uint32_t char_length; 12.243 + 12.244 + if (char_size < 2) 12.245 + char_length = 0; 12.246 + else 12.247 + { 12.248 + char_length = char_size - 2; 12.249 + 12.250 + if (char_size > Ssi_char_length_limit) 12.251 + char_length = Ssi_char_length_limit; 12.252 + } 12.253 + 12.254 + /* Clear the status. */ 12.255 + 12.256 + _regs[Ssi_control0] = _regs[Ssi_control0] | Ssi_trans_flush | Ssi_recv_flush; 12.257 + _regs[Ssi_status] = 0; 12.258 + 12.259 + /* Indicate the desired character size. 12.260 + 12.261 + Use active low device selection, SPI format with active low clock, with 12.262 + data driven on the falling (asserted) clock and sampled on the rising 12.263 + clock 12.264 + 12.265 + The unfinished flag prevents the transaction from finishing if the FIFO is 12.266 + empty. It is not used here since it appears to prevent any meaningful 12.267 + testing of the busy and end flags. */ 12.268 + 12.269 + _regs[Ssi_control1] = (char_length << Ssi_char_length_shift) | 12.270 + ((Ssi_trans_threshold_limit / 2) << Ssi_trans_threshold_shift) | 12.271 + Ssi_format_spi | Ssi_active_ce2_low | 12.272 + Spi_clock_assert_drive | Spi_clock_idle_high_level; 12.273 +} 12.274 + 12.275 +/* Transfer the given number of bytes from a buffer using the given unit size in 12.276 + bytes and character size in bits. */ 12.277 + 12.278 +uint32_t 12.279 +Spi_jz4780_channel::send(uint32_t bytes, const uint8_t data[], uint8_t unit_size, 12.280 + uint8_t char_size) 12.281 +{ 12.282 + configure_transfer(char_size); 12.283 + 12.284 + uint32_t transferred; 12.285 + uint32_t char_mask = (1 << char_size) - 1; 12.286 + 12.287 + for (transferred = 0; transferred < bytes; transferred += unit_size) 12.288 + { 12.289 + uint32_t value = 0; 12.290 + 12.291 + for (uint8_t byte = 0; byte < unit_size; byte++) 12.292 + value = (value << 8) | data[transferred + byte]; 12.293 + 12.294 + /* Relocate any command bit to bit 16 for byte characters. */ 12.295 + 12.296 + uint32_t command = (char_size < 16) && (value & (1 << char_size)) ? (1 << 16) : 0; 12.297 + 12.298 + /* Combine the significant portion of the character with the command. */ 12.299 + 12.300 + value = (value & char_mask) | command; 12.301 + _regs[Ssi_data] = value; 12.302 + } 12.303 + 12.304 + /* Wait for the busy condition to clear or for a limited period. */ 12.305 + 12.306 + for (unsigned int i = 0; i < (1 << 20) && (_regs[Ssi_status] & Ssi_trans_busy); i++); 12.307 + 12.308 + return transferred; 12.309 +} 12.310 + 12.311 +/* Transfer the given number of bytes from a DMA region using the given 12.312 + unit size in bytes and character size in bits. */ 12.313 + 12.314 +uint32_t Spi_jz4780_channel::transfer(l4re_dma_space_dma_addr_t paddr, 12.315 + uint32_t count, uint8_t unit_size, 12.316 + uint8_t char_size) 12.317 +{ 12.318 + configure_transfer(char_size); 12.319 + 12.320 + uint32_t transferred = 0; 12.321 + uint32_t unit_count = count / unit_size; 12.322 + uint32_t to_transfer = _dma->transfer(paddr, _spi_start + Ssi_data, 12.323 + unit_count, true, false, 12.324 + unit_size, unit_size, unit_size, 12.325 + _request_type); 12.326 + 12.327 + if (to_transfer) 12.328 + transferred = to_transfer ? (unit_count - _dma->wait()) * unit_size : 0; 12.329 + 12.330 + /* Wait for the busy condition to clear or for a limited period. */ 12.331 + 12.332 + for (unsigned int i = 0; i < (1 << 20) && (_regs[Ssi_status] & Ssi_trans_busy); i++); 12.333 + 12.334 + return transferred; 12.335 +} 12.336 + 12.337 + 12.338 + 12.339 +/* Initialise the peripheral abstraction. */ 12.340 + 12.341 +Spi_jz4780_chip::Spi_jz4780_chip(l4_addr_t spi_start, l4_addr_t start, 12.342 + l4_addr_t end, Cpm_jz4780_chip *cpm) 12.343 +: _spi_start(spi_start), _start(start), _end(end), _cpm(cpm) 12.344 +{ 12.345 +} 12.346 + 12.347 +Spi_jz4780_channel * 12.348 +Spi_jz4780_chip::get_channel(uint8_t channel, Dma_jz4780_channel *dma, 12.349 + uint64_t frequency) 12.350 +{ 12.351 + // NOTE: Only sending is supported. 12.352 + 12.353 + enum Dma_jz4780_request_type request_types[] = {Dma_request_ssi0_out, Dma_request_ssi1_out}; 12.354 + enum Clock_identifiers clocks[] = {Clock_ssi0, Clock_ssi1}; 12.355 + 12.356 + if (channel < 2) 12.357 + return new Spi_jz4780_channel(_spi_start + channel * Ssi_block_offset, 12.358 + _start + channel * Ssi_block_offset, 12.359 + clocks[channel], 12.360 + _cpm, dma, request_types[channel], frequency); 12.361 + else 12.362 + throw -L4_EINVAL; 12.363 +} 12.364 + 12.365 + 12.366 + 12.367 +/* C language interface. */ 12.368 + 12.369 +void *jz4780_spi_init(l4_addr_t spi_start, l4_addr_t start, l4_addr_t end, void *cpm) 12.370 +{ 12.371 + return new Spi_jz4780_chip(spi_start, start, end, static_cast<Cpm_jz4780_chip *>(cpm)); 12.372 +} 12.373 + 12.374 +void *jz4780_spi_get_channel(void *spi, uint8_t channel, void *dma, uint64_t frequency) 12.375 +{ 12.376 + return static_cast<Spi_jz4780_chip *>(spi)->get_channel(channel, 12.377 + static_cast<Dma_jz4780_channel *>(dma), frequency); 12.378 +} 12.379 + 12.380 +uint32_t jz4780_spi_send(void *channel, uint32_t bytes, const uint8_t data[], 12.381 + uint8_t unit_size, uint8_t char_size) 12.382 +{ 12.383 + return static_cast<Spi_jz4780_channel *>(channel)->send(bytes, data, unit_size, char_size); 12.384 +} 12.385 + 12.386 +uint32_t jz4780_spi_transfer(void *channel, l4re_dma_space_dma_addr_t paddr, 12.387 + uint32_t count, uint8_t unit_size, uint8_t char_size) 12.388 +{ 12.389 + return static_cast<Spi_jz4780_channel *>(channel)->transfer(paddr, count, unit_size, char_size); 12.390 +}
13.1 --- a/pkg/landfall-examples/hw_info/common.h Fri Nov 03 19:58:11 2023 +0100 13.2 +++ b/pkg/landfall-examples/hw_info/common.h Tue Nov 07 19:20:32 2023 +0100 13.3 @@ -35,9 +35,8 @@ 13.4 13.5 void *aic_get_channel(void *aic, int num, void *channel); 13.6 13.7 -long aic_get_buffer(void *channel, uint32_t count, l4_addr_t *addr); 13.8 - 13.9 -unsigned int aic_transfer(void *channel, uint32_t count, uint32_t sample_rate, 13.10 +unsigned int aic_transfer(void *channel, l4re_dma_space_dma_addr_t paddr, 13.11 + uint32_t count, uint32_t sample_rate, 13.12 uint8_t sample_size); 13.13 13.14 13.15 @@ -168,12 +167,22 @@ 13.16 13.17 /* SPI adapter functions. */ 13.18 13.19 -void *spi_get_channel(void *clock_chip, int clock_pin, 13.20 - void *data_chip, int data_pin, 13.21 - void *enable_chip, int enable_pin, 13.22 - uint32_t frequency); 13.23 +void *spi_init(l4_addr_t spi_start, l4_addr_t start, l4_addr_t end, void *cpm); 13.24 + 13.25 +void *spi_get_channel(void *spi, uint8_t num, void *channel, uint64_t frequency); 13.26 13.27 -void spi_send(void *channel, int bytes, const uint8_t data[]); 13.28 +void *spi_get_channel_gpio(void *clock_chip, int clock_pin, 13.29 + void *data_chip, int data_pin, 13.30 + void *enable_chip, int enable_pin, 13.31 + uint64_t frequency); 13.32 + 13.33 +void spi_send(void *channel, int bytes, const uint8_t data[], 13.34 + uint8_t unit_size, uint8_t char_size); 13.35 + 13.36 +void spi_send_gpio(void *channel, int bytes, const uint8_t data[]); 13.37 + 13.38 +uint32_t spi_transfer(void *channel, l4re_dma_space_dma_addr_t paddr, 13.39 + uint32_t count, uint8_t unit_size, uint8_t char_size); 13.40 13.41 13.42 13.43 @@ -181,7 +190,7 @@ 13.44 13.45 enum memory_regions 13.46 { 13.47 - AIC, CPM, DMA, GPIO, I2C 13.48 + AIC, CPM, DMA, GPIO, I2C, SSI 13.49 }; 13.50 13.51
14.1 --- a/pkg/landfall-examples/hw_info/hw_info.c Fri Nov 03 19:58:11 2023 +0100 14.2 +++ b/pkg/landfall-examples/hw_info/hw_info.c Tue Nov 07 19:20:32 2023 +0100 14.3 @@ -218,17 +218,22 @@ 14.4 } 14.5 } 14.6 14.7 +static struct dma_region *_get_dma_region(void) 14.8 +{ 14.9 + int num = get_region_number(num_dma_regions); 14.10 + 14.11 + if (num < 0) 14.12 + return NULL; 14.13 + 14.14 + return &dma_regions[num]; 14.15 +} 14.16 14.17 14.18 -/* AIC/I2S configuration. */ 14.19 - 14.20 -static l4_uint32_t aic_irq_start = 0, aic_irq_end = 0; 14.21 14.22 /* AIC/I2S operations. */ 14.23 14.24 static void new_aic_channel(void *aic) 14.25 { 14.26 - l4_cap_idx_t irqcap; 14.27 int num = get_channel_number(num_aic_channels); 14.28 void *channel; 14.29 14.30 @@ -240,64 +245,23 @@ 14.31 if (channel == NULL) 14.32 return; 14.33 14.34 - irqcap = l4re_util_cap_alloc(); 14.35 - 14.36 - if (init_irq(num, irqcap, aic_irq_start, aic_irq_end)) 14.37 - return; 14.38 - 14.39 aic_channels[num] = aic_get_channel(aic, num, channel); 14.40 - aic_irqs[num] = irqcap; 14.41 -} 14.42 - 14.43 -static void set_aic_buffer(void) 14.44 -{ 14.45 - char *token; 14.46 - FILE *fp; 14.47 - void *channel = get_channel(num_aic_channels, aic_channels, NULL); 14.48 - unsigned int size; 14.49 - l4_addr_t vaddr; 14.50 - 14.51 - if (channel == NULL) 14.52 - return; 14.53 - 14.54 - if (!read_number("Buffer size", &size)) 14.55 - return; 14.56 - 14.57 - if (aic_get_buffer(channel, size, &vaddr)) 14.58 - { 14.59 - printf("Could not get buffer.\n"); 14.60 - return; 14.61 - } 14.62 - 14.63 - memset((void *) vaddr, 0, size); 14.64 - 14.65 - if ((token = read_token("Filename")) == NULL) 14.66 - return; 14.67 - 14.68 - /* Populate the region from the file. */ 14.69 - 14.70 - fp = fopen(token, "r"); 14.71 - 14.72 - if (fp == NULL) 14.73 - { 14.74 - printf("File not readable.\n"); 14.75 - return; 14.76 - } 14.77 - 14.78 - fread((char *) vaddr, sizeof(char), size, fp); 14.79 - fclose(fp); 14.80 - 14.81 - l4_cache_flush_data(vaddr, vaddr + size); 14.82 } 14.83 14.84 static void aic_transfer_data(void) 14.85 { 14.86 void *channel = get_channel(num_aic_channels, aic_channels, NULL); 14.87 - unsigned int count, rate, resolution, transferred; 14.88 + struct dma_region *region; 14.89 + uint32_t count, rate, resolution, transferred; 14.90 14.91 if (channel == NULL) 14.92 return; 14.93 14.94 + region = _get_dma_region(); 14.95 + 14.96 + if (region == NULL) 14.97 + return; 14.98 + 14.99 if (!read_number("Sample size", &count)) 14.100 return; 14.101 14.102 @@ -307,7 +271,7 @@ 14.103 if (!read_number("Sample resolution", &resolution)) 14.104 return; 14.105 14.106 - transferred = aic_transfer(channel, count, rate, resolution); 14.107 + transferred = aic_transfer(channel, region->paddr, count, rate, resolution); 14.108 14.109 printf("Transferred: %d\n", transferred); 14.110 } 14.111 @@ -507,16 +471,6 @@ 14.112 return init_irq(0, dma_irq, dma_irq_start, dma_irq_end); 14.113 } 14.114 14.115 -static struct dma_region *_get_dma_region(void) 14.116 -{ 14.117 - int num = get_region_number(num_dma_regions); 14.118 - 14.119 - if (num < 0) 14.120 - return NULL; 14.121 - 14.122 - return &dma_regions[num]; 14.123 -} 14.124 - 14.125 static void list_dma_regions(void) 14.126 { 14.127 unsigned int num; 14.128 @@ -627,7 +581,7 @@ 14.129 14.130 static void dma_transfer_data(void) 14.131 { 14.132 - unsigned int count, to_transfer, transferred; 14.133 + uint32_t count, to_transfer, transferred; 14.134 unsigned int source_address, destination_address, source_width, destination_width, 14.135 transfer_unit_size, request_type; 14.136 int source_increment, destination_increment; 14.137 @@ -670,11 +624,11 @@ 14.138 l4_cache_inv_data(dma_regions[i].vaddr, dma_regions[i].vaddr + dma_regions[i].size); 14.139 14.140 to_transfer = dma_transfer(channel, source_address, destination_address, 14.141 - count, 14.142 - source_increment, destination_increment, 14.143 - source_width, destination_width, 14.144 - transfer_unit_size, 14.145 - request_type); 14.146 + count, 14.147 + source_increment, destination_increment, 14.148 + source_width, destination_width, 14.149 + transfer_unit_size, 14.150 + request_type); 14.151 14.152 transferred = to_transfer ? count - dma_wait(channel) : 0; 14.153 14.154 @@ -1043,7 +997,27 @@ 14.155 14.156 /* SPI operations. */ 14.157 14.158 -static void new_spi_channel(void *gpio[]) 14.159 +static void new_spi_channel(void *spi) 14.160 +{ 14.161 + int num = get_channel_number(num_spi_channels); 14.162 + void *channel; 14.163 + uint32_t frequency; 14.164 + 14.165 + if (num < 0) 14.166 + return; 14.167 + 14.168 + channel = get_channel(num_dma_channels, dma_channels, NULL); 14.169 + 14.170 + if (channel == NULL) 14.171 + return; 14.172 + 14.173 + if (!read_number("Frequency", &frequency)) 14.174 + return; 14.175 + 14.176 + spi_channels[num] = spi_get_channel(spi, num, channel, frequency); 14.177 +} 14.178 + 14.179 +static void new_spi_channel_gpio(void *gpio[]) 14.180 { 14.181 unsigned int clock_port, clock_pin, data_port, data_pin, enable_port, enable_pin; 14.182 int num = get_channel_number(num_spi_channels); 14.183 @@ -1064,13 +1038,13 @@ 14.184 if (!read_number("Frequency", &frequency)) 14.185 return; 14.186 14.187 - spi_channels[num] = spi_get_channel(gpio[clock_port], clock_pin, 14.188 - gpio[data_port], data_pin, 14.189 - gpio[enable_port], enable_pin, 14.190 - frequency); 14.191 + spi_channels[num] = spi_get_channel_gpio(gpio[clock_port], clock_pin, 14.192 + gpio[data_port], data_pin, 14.193 + gpio[enable_port], enable_pin, 14.194 + frequency); 14.195 } 14.196 14.197 -static void spi_send_data(void) 14.198 +static void spi_send_data_gpio(void) 14.199 { 14.200 void *channel = get_channel(num_spi_channels, spi_channels, NULL); 14.201 int bytes; 14.202 @@ -1085,7 +1059,59 @@ 14.203 bytes++; 14.204 } 14.205 14.206 - spi_send(channel, bytes, buffer); 14.207 + spi_send_gpio(channel, bytes, buffer); 14.208 +} 14.209 + 14.210 +static void spi_send_data_units(void) 14.211 +{ 14.212 + void *channel = get_channel(num_spi_channels, spi_channels, NULL); 14.213 + unsigned int char_size, unit_size, value; 14.214 + uint8_t buffer[256]; 14.215 + int byte = 0; 14.216 + 14.217 + if (!read_number("Unit size", &unit_size)) 14.218 + return; 14.219 + 14.220 + if (!read_number("Character size", &char_size)) 14.221 + return; 14.222 + 14.223 + /* Read hex digits for bytes. Multiple bytes make up each unit and are read 14.224 + from most to least significant. Where the unit size exceeds the character 14.225 + size, the last bit before the character indicates the GPC bit. */ 14.226 + 14.227 + while ((byte < 256) && read_encoded_number(NULL, "%2x", &value)) 14.228 + buffer[byte++] = value; 14.229 + 14.230 + spi_send(channel, byte, (uint8_t *) buffer, unit_size, char_size); 14.231 +} 14.232 + 14.233 +static void spi_transfer_data(void) 14.234 +{ 14.235 + void *channel = get_channel(num_spi_channels, spi_channels, NULL); 14.236 + struct dma_region *region; 14.237 + unsigned int char_size, unit_size; 14.238 + uint32_t count, transferred; 14.239 + 14.240 + if (channel == NULL) 14.241 + return; 14.242 + 14.243 + region = _get_dma_region(); 14.244 + 14.245 + if (region == NULL) 14.246 + return; 14.247 + 14.248 + if (!read_number("Transfer size", &count)) 14.249 + return; 14.250 + 14.251 + if (!read_number("Unit size", &unit_size)) 14.252 + return; 14.253 + 14.254 + if (!read_number("Character size", &char_size)) 14.255 + return; 14.256 + 14.257 + transferred = spi_transfer(channel, region->paddr, count, unit_size, char_size); 14.258 + 14.259 + printf("Transferred: %d\n", transferred); 14.260 } 14.261 14.262 14.263 @@ -1102,8 +1128,6 @@ 14.264 list_channels(num_aic_channels, aic_channels); 14.265 else if (!strcmp(token, "c") || !strcmp(token, "channel")) 14.266 new_aic_channel(aic); 14.267 - else if (!strcmp(token, "s") || !strcmp(token, "set")) 14.268 - set_aic_buffer(); 14.269 else if (!strcmp(token, "t") || !strcmp(token, "transfer")) 14.270 aic_transfer_data(); 14.271 else 14.272 @@ -1203,7 +1227,7 @@ 14.273 list_i2c_channels(); 14.274 } 14.275 14.276 -static void handle_spi(void *gpio[]) 14.277 +static void handle_spi(void *spi, void *gpio[]) 14.278 { 14.279 char *token; 14.280 14.281 @@ -1212,11 +1236,17 @@ 14.282 if (!strcmp(token, "l") || !strcmp(token, "list")) 14.283 list_channels(num_spi_channels, spi_channels); 14.284 else if (!strcmp(token, "c") || !strcmp(token, "channel")) 14.285 - new_spi_channel(gpio); 14.286 + new_spi_channel(spi); 14.287 + else if (!strcmp(token, "g") || !strcmp(token, "gpio") || !strcmp(token, "gpio-channel")) 14.288 + new_spi_channel_gpio(gpio); 14.289 else if (!strcmp(token, "s") || !strcmp(token, "send")) 14.290 - spi_send_data(); 14.291 + spi_send_data_gpio(); 14.292 + else if (!strcmp(token, "S") || !strcmp(token, "send-units")) 14.293 + spi_send_data_units(); 14.294 + else if (!strcmp(token, "t") || !strcmp(token, "transfer")) 14.295 + spi_transfer_data(); 14.296 else 14.297 - printf("spi channel | list | send\n"); 14.298 + printf("spi channel | gpio-channel | list | send | send-units | transfer\n"); 14.299 } 14.300 else 14.301 list_channels(num_spi_channels, spi_channels); 14.302 @@ -1232,7 +1262,9 @@ 14.303 l4_addr_t dma_base = 0, dma_base_end = 0; 14.304 l4_addr_t gpio_base = 0, gpio_base_end = 0; 14.305 l4_addr_t i2c_base = 0, i2c_base_end = 0; 14.306 - void *aic, *cpm, *dma, *gpio[num_gpio_ports], *i2c; 14.307 + l4_addr_t ssi_base = 0, ssi_base_end = 0; 14.308 + l4_addr_t ssi_phys_base = 0, ssi_phys_base_end = 0; 14.309 + void *aic, *cpm, *dma, *gpio[num_gpio_ports], *i2c, *spi; 14.310 int result = 0; 14.311 unsigned int port; 14.312 14.313 @@ -1303,10 +1335,15 @@ 14.314 14.315 aic = aic_init(aic_phys_base, aic_base, aic_base_end, cpm); 14.316 14.317 - if (get_irq(memory_regions[AIC], &aic_irq_start, &aic_irq_end) < 0) 14.318 + printf("Access SSI...\n"); 14.319 + 14.320 + if ((result = get_memory_complete(memory_regions[SSI], &ssi_base, &ssi_base_end, 14.321 + &ssi_phys_base, &ssi_phys_base_end)) < 0) 14.322 return 1; 14.323 14.324 - printf("IRQ range at %d...%d.\n", aic_irq_start, aic_irq_end); 14.325 + printf("SSI at 0x%lx...0x%lx.\n", ssi_base, ssi_base_end); 14.326 + 14.327 + spi = spi_init(ssi_phys_base, ssi_base, ssi_base_end, cpm); 14.328 14.329 /* Start the interactive session. */ 14.330 14.331 @@ -1318,7 +1355,7 @@ 14.332 14.333 printf("> "); 14.334 14.335 - token = fgets(cmdline, 64, stdin); 14.336 + token = fgets(cmdline, 256, stdin); 14.337 14.338 if (token == NULL) 14.339 break; 14.340 @@ -1354,9 +1391,11 @@ 14.341 /* SPI commands. */ 14.342 14.343 else if (!strcmp(token, "s") || !strcmp(token, "spi")) 14.344 - handle_spi(gpio); 14.345 + handle_spi(spi, gpio); 14.346 14.347 - else 14.348 + /* Comments and blank lines. */ 14.349 + 14.350 + else if (strncmp(token, "#", 1) && strlen(token)) 14.351 printf("Command?\n"); 14.352 } 14.353
15.1 --- a/pkg/landfall-examples/hw_info/jz4780.c Fri Nov 03 19:58:11 2023 +0100 15.2 +++ b/pkg/landfall-examples/hw_info/jz4780.c Tue Nov 07 19:20:32 2023 +0100 15.3 @@ -19,12 +19,21 @@ 15.4 * Boston, MA 02110-1301, USA 15.5 */ 15.6 15.7 -#include <l4/devices/aic-x1600.h> /* NOTE: To be replaced. */ 15.8 +/* NOTE: AIC support should be replaced. The CI20 should be able to send I2S 15.9 + audio over HDMI or via its internal codec to the headphone socket. */ 15.10 + 15.11 +#include <l4/devices/aic-x1600.h> 15.12 + 15.13 #include <l4/devices/cpm-jz4780.h> 15.14 #include <l4/devices/dma-jz4780.h> 15.15 #include <l4/devices/gpio-jz4780.h> 15.16 #include <l4/devices/i2c-jz4780.h> 15.17 + 15.18 +/* GPIO-based SPI can use arbitrary pins, whereas only the secondary header 15.19 + provides pins like GPC. */ 15.20 + 15.21 #include <l4/devices/spi-gpio.h> 15.22 +#include <l4/devices/spi-jz4780.h> 15.23 #include "common.h" 15.24 15.25 15.26 @@ -41,14 +50,11 @@ 15.27 return x1600_aic_get_channel(aic, num, channel); 15.28 } 15.29 15.30 -long aic_get_buffer(void *channel, uint32_t count, l4_addr_t *addr) 15.31 +unsigned int aic_transfer(void *channel, l4re_dma_space_dma_addr_t paddr, 15.32 + uint32_t count, uint32_t sample_rate, 15.33 + uint8_t sample_size) 15.34 { 15.35 - return x1600_aic_get_buffer(channel, count, addr); 15.36 -} 15.37 - 15.38 -unsigned int aic_transfer(void *channel, uint32_t count, uint32_t sample_rate, uint8_t sample_size) 15.39 -{ 15.40 - return x1600_aic_transfer(channel, count, sample_rate, sample_size); 15.41 + return x1600_aic_transfer(channel, paddr, count, sample_rate, sample_size); 15.42 } 15.43 15.44 15.45 @@ -326,19 +332,42 @@ 15.46 15.47 /* SPI adapter functions. */ 15.48 15.49 -void *spi_get_channel(void *clock_chip, int clock_pin, 15.50 - void *data_chip, int data_pin, 15.51 - void *enable_chip, int enable_pin, 15.52 - uint32_t frequency) 15.53 +void *spi_init(l4_addr_t spi_start, l4_addr_t start, l4_addr_t end, void *cpm) 15.54 { 15.55 - return spi_gpio_get_channel(clock_chip, clock_pin, data_chip, data_pin, enable_chip, enable_pin, frequency); 15.56 + return jz4780_spi_init(spi_start, start, end, cpm); 15.57 +} 15.58 + 15.59 +void *spi_get_channel(void *spi, uint8_t num, void *channel, uint64_t frequency) 15.60 +{ 15.61 + return jz4780_spi_get_channel(spi, num, channel, frequency); 15.62 } 15.63 15.64 -void spi_send(void *channel, int bytes, const uint8_t data[]) 15.65 +void *spi_get_channel_gpio(void *clock_chip, int clock_pin, 15.66 + void *data_chip, int data_pin, 15.67 + void *enable_chip, int enable_pin, 15.68 + uint64_t frequency) 15.69 +{ 15.70 + return spi_gpio_get_channel(clock_chip, clock_pin, data_chip, data_pin, 15.71 + enable_chip, enable_pin, frequency); 15.72 +} 15.73 + 15.74 +void spi_send(void *channel, int bytes, const uint8_t data[], uint8_t unit_size, 15.75 + uint8_t char_size) 15.76 +{ 15.77 + jz4780_spi_send(channel, bytes, data, unit_size, char_size); 15.78 +} 15.79 + 15.80 +void spi_send_gpio(void *channel, int bytes, const uint8_t data[]) 15.81 { 15.82 spi_gpio_send(channel, bytes, data); 15.83 } 15.84 15.85 +uint32_t spi_transfer(void *channel, l4re_dma_space_dma_addr_t paddr, 15.86 + uint32_t count, uint8_t unit_size, uint8_t char_size) 15.87 +{ 15.88 + return jz4780_spi_transfer(channel, paddr, count, unit_size, char_size); 15.89 +} 15.90 + 15.91 15.92 15.93 /* Memory regions. */ 15.94 @@ -349,6 +378,7 @@ 15.95 [DMA] = "jz4780-dma", 15.96 [GPIO] = "jz4780-gpio", 15.97 [I2C] = "jz4780-i2c", 15.98 + [SSI] = "jz4780-ssi", 15.99 }; 15.100 15.101 15.102 @@ -399,7 +429,6 @@ 15.103 {"ssi", Clock_ssi, "SSI"}, 15.104 {"ssi0", Clock_ssi0, "SSI0"}, 15.105 {"ssi1", Clock_ssi1, "SSI1"}, 15.106 - {"ssi2", Clock_ssi2, "SSI2"}, 15.107 {"uart0", Clock_uart0, "UART0"}, 15.108 {"uart1", Clock_uart1, "UART1"}, 15.109 {"uart2", Clock_uart2, "UART2"}, 15.110 @@ -416,9 +445,9 @@ 15.111 15.112 const unsigned int num_dma_channels = 32; 15.113 15.114 -struct dma_region dma_regions[2]; 15.115 +struct dma_region dma_regions[8]; 15.116 15.117 -const unsigned int num_dma_regions = 2; 15.118 +const unsigned int num_dma_regions = 8; 15.119 15.120 l4_cap_idx_t dma_irq = L4_INVALID_CAP; 15.121
16.1 --- a/pkg/landfall-examples/hw_info/x1600.c Fri Nov 03 19:58:11 2023 +0100 16.2 +++ b/pkg/landfall-examples/hw_info/x1600.c Tue Nov 07 19:20:32 2023 +0100 16.3 @@ -41,14 +41,11 @@ 16.4 return x1600_aic_get_channel(aic, num, channel); 16.5 } 16.6 16.7 -long aic_get_buffer(void *channel, uint32_t count, l4_addr_t *addr) 16.8 +unsigned int aic_transfer(void *channel, l4re_dma_space_dma_addr_t paddr, 16.9 + uint32_t count, uint32_t sample_rate, 16.10 + uint8_t sample_size) 16.11 { 16.12 - return x1600_aic_get_buffer(channel, count, addr); 16.13 -} 16.14 - 16.15 -unsigned int aic_transfer(void *channel, uint32_t count, uint32_t sample_rate, uint8_t sample_size) 16.16 -{ 16.17 - return x1600_aic_transfer(channel, count, sample_rate, sample_size); 16.18 + return x1600_aic_transfer(channel, paddr, count, sample_rate, sample_size); 16.19 } 16.20 16.21 16.22 @@ -326,19 +323,50 @@ 16.23 16.24 /* SPI adapter functions. */ 16.25 16.26 -void *spi_get_channel(void *clock_chip, int clock_pin, 16.27 - void *data_chip, int data_pin, 16.28 - void *enable_chip, int enable_pin, 16.29 - uint32_t frequency) 16.30 +void *spi_init(l4_addr_t spi_start, l4_addr_t start, l4_addr_t end, void *cpm) 16.31 +{ 16.32 + (void) spi_start; (void) start; (void) end; (void) cpm; 16.33 + return NULL; 16.34 +} 16.35 + 16.36 +void *spi_get_channel(void *spi, uint8_t num, void *channel, uint64_t frequency) 16.37 +{ 16.38 + (void) spi; (void) num; (void) channel; (void) frequency; 16.39 + return NULL; 16.40 +} 16.41 + 16.42 +void *spi_get_channel_gpio(void *clock_chip, int clock_pin, 16.43 + void *data_chip, int data_pin, 16.44 + void *enable_chip, int enable_pin, 16.45 + uint64_t frequency) 16.46 { 16.47 return spi_gpio_get_channel(clock_chip, clock_pin, data_chip, data_pin, enable_chip, enable_pin, frequency); 16.48 } 16.49 16.50 -void spi_send(void *channel, int bytes, const uint8_t data[]) 16.51 +void spi_send(void *channel, int bytes, const uint8_t data[], uint8_t unit_size, 16.52 + uint8_t char_size) 16.53 +{ 16.54 + /* NOTE: Not yet supported. */ 16.55 + 16.56 + (void) channel; (void) bytes; (void) data; (void) unit_size; (void) char_size; 16.57 + // x1600_spi_send(channel, bytes, data, unit_size, char_size); 16.58 +} 16.59 + 16.60 +void spi_send_gpio(void *channel, int bytes, const uint8_t data[]) 16.61 { 16.62 spi_gpio_send(channel, bytes, data); 16.63 } 16.64 16.65 +uint32_t spi_transfer(void *channel, l4re_dma_space_dma_addr_t paddr, 16.66 + uint32_t count, uint8_t unit_size, uint8_t char_size) 16.67 +{ 16.68 + /* NOTE: Not yet supported. */ 16.69 + 16.70 + (void) channel; (void) paddr; (void) count; (void) unit_size; (void) char_size; 16.71 + // return x1600_spi_transfer(channel, paddr, count, unit_size, char_size); 16.72 + return 0; 16.73 +} 16.74 + 16.75 16.76 16.77 /* Memory regions. */ 16.78 @@ -349,6 +377,7 @@ 16.79 [DMA] = "x1600-dma", 16.80 [GPIO] = "x1600-gpio", 16.81 [I2C] = "x1600-i2c", 16.82 + [SSI] = "x1600-ssi", 16.83 }; 16.84 16.85 16.86 @@ -377,7 +406,7 @@ 16.87 {"apb", Clock_pclock, "APB"}, 16.88 {"aic", Clock_aic, "AIC"}, 16.89 {"dma", Clock_dma, "DMA"}, 16.90 - {"lcd", Clock_lcd_pixel0, "LCD pixel"}, 16.91 + {"lcd0", Clock_lcd_pixel0, "LCD pixel"}, 16.92 {"msc0", Clock_msc0, "MSC0"}, 16.93 {"msc1", Clock_msc1, "MSC1"}, 16.94 {"otg", Clock_otg0, "USB OTG"}, 16.95 @@ -387,7 +416,7 @@ 16.96 {"i2s1", Clock_i2s1, "I2S1"}, 16.97 {"i2s0r", Clock_i2s0_rx, "I2S0 RX"}, 16.98 {"i2s0t", Clock_i2s0_tx, "I2S0 TX"}, 16.99 - {"ssi", Clock_ssi0, "SSI"}, 16.100 + {"ssi0", Clock_ssi0, "SSI"}, 16.101 {"uart0", Clock_uart0, "UART0"}, 16.102 {"uart1", Clock_uart1, "UART1"}, 16.103 {"uart2", Clock_uart2, "UART2"}, 16.104 @@ -403,9 +432,9 @@ 16.105 16.106 const unsigned int num_dma_channels = 32; 16.107 16.108 -struct dma_region dma_regions[2]; 16.109 +struct dma_region dma_regions[8]; 16.110 16.111 -const unsigned int num_dma_regions = 2; 16.112 +const unsigned int num_dma_regions = 8; 16.113 16.114 l4_cap_idx_t dma_irq = L4_INVALID_CAP; 16.115