1.1 --- a/conf/landfall-examples/input-keypad.txt Sat Oct 28 01:15:45 2023 +0200 1.2 +++ b/conf/landfall-examples/input-keypad.txt Sun Oct 29 16:14:38 2023 +0100 1.3 @@ -1,1 +1,1 @@ 1.4 -rom/libkeypad_qi_lb60.so 1.5 \ No newline at end of file 1.6 +rom/libkeypad_lx16.so 1.7 \ No newline at end of file
2.1 --- a/conf/landfall-examples/mips-jz4740-panel.txt Sat Oct 28 01:15:45 2023 +0200 2.2 +++ b/conf/landfall-examples/mips-jz4740-panel.txt Sun Oct 29 16:14:38 2023 +0100 2.3 @@ -1,1 +1,1 @@ 2.4 -rom/libpanel_qi_lb60.so 2.5 \ No newline at end of file 2.6 +rom/libpanel_lx16.so 2.7 \ No newline at end of file
3.1 --- a/pkg/devices/include/clocks.h Sat Oct 28 01:15:45 2023 +0200 3.2 +++ b/pkg/devices/include/clocks.h Sun Oct 29 16:14:38 2023 +0100 3.3 @@ -87,6 +87,7 @@ 3.4 Clock_uart1, 3.5 Clock_uart2, 3.6 Clock_uart3, 3.7 + Clock_uart4, 3.8 Clock_udc, 3.9 Clock_uhc, 3.10 Clock_uprt,
4.1 --- a/pkg/devices/lib/cpm/src/jz4780.cc Sat Oct 28 01:15:45 2023 +0200 4.2 +++ b/pkg/devices/lib/cpm/src/jz4780.cc Sun Oct 29 16:14:38 2023 +0100 4.3 @@ -549,6 +549,12 @@ 4.4 return (void *) new Cpm_jz4780_chip(cpm_base); 4.5 } 4.6 4.7 +const char * 4.8 +jz4780_cpm_clock_type(void *cpm, enum Clock_identifiers clock) 4.9 +{ 4.10 + return static_cast<Cpm_jz4780_chip *>(cpm)->clock_type(clock); 4.11 +} 4.12 + 4.13 int 4.14 jz4780_cpm_have_clock(void *cpm, enum Clock_identifiers clock) 4.15 {
5.1 --- a/pkg/devices/lib/cpm/src/x1600.cc Sat Oct 28 01:15:45 2023 +0200 5.2 +++ b/pkg/devices/lib/cpm/src/x1600.cc Sun Oct 29 16:14:38 2023 +0100 5.3 @@ -460,6 +460,7 @@ 5.4 &clock_uart1, 5.5 &clock_uart2, 5.6 &clock_uart3, 5.7 + &clock_none, // Clock_uart4 5.8 &clock_none, // Clock_udc 5.9 &clock_none, // Clock_uhc 5.10 &clock_none, // Clock_uprt
6.1 --- a/pkg/devices/lib/dma/include/dma-jz4730.h Sat Oct 28 01:15:45 2023 +0200 6.2 +++ b/pkg/devices/lib/dma/include/dma-jz4730.h Sun Oct 29 16:14:38 2023 +0100 6.3 @@ -44,12 +44,12 @@ 6.4 Dma_request_uart1_in = 19, 6.5 Dma_request_uart0_out = 20, 6.6 Dma_request_uart0_in = 21, 6.7 - Dma_request_ssi_send_empty = 22, 6.8 - Dma_request_ssi_recv_full = 23, 6.9 - Dma_request_aic_send_empty = 24, 6.10 - Dma_request_aic_recv_full = 25, 6.11 - Dma_request_msc_send_empty = 26, 6.12 - Dma_request_msc_recv_full = 27, 6.13 + Dma_request_ssi_out = 22, 6.14 + Dma_request_ssi_in = 23, 6.15 + Dma_request_aic_out = 24, 6.16 + Dma_request_aic_in = 25, 6.17 + Dma_request_msc_out = 26, 6.18 + Dma_request_msc_in = 27, 6.19 Dma_request_ost2_underflow = 28, 6.20 }; 6.21
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/pkg/devices/lib/dma/include/dma-jz4780.h Sun Oct 29 16:14:38 2023 +0100 7.3 @@ -0,0 +1,191 @@ 7.4 +/* 7.5 + * DMA support for the JZ4780. 7.6 + * 7.7 + * Copyright (C) 2021, 2023 Paul Boddie <paul@boddie.org.uk> 7.8 + * 7.9 + * This program is free software; you can redistribute it and/or 7.10 + * modify it under the terms of the GNU General Public License as 7.11 + * published by the Free Software Foundation; either version 2 of 7.12 + * the License, or (at your option) any later version. 7.13 + * 7.14 + * This program is distributed in the hope that it will be useful, 7.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 7.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 7.17 + * GNU General Public License for more details. 7.18 + * 7.19 + * You should have received a copy of the GNU General Public License 7.20 + * along with this program; if not, write to the Free Software 7.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 7.22 + * Boston, MA 02110-1301, USA 7.23 + */ 7.24 + 7.25 +#pragma once 7.26 + 7.27 +#include <l4/sys/types.h> 7.28 +#include <stdint.h> 7.29 + 7.30 + 7.31 + 7.32 +/* Enumerated types for various transfer parameters. */ 7.33 + 7.34 +enum Dma_jz4780_request_type 7.35 +{ 7.36 + Dma_request_i2s1_out = 4, 7.37 + Dma_request_i2s1_in = 5, 7.38 + Dma_request_i2s0_out = 6, 7.39 + Dma_request_i2s0_in = 7, 7.40 + Dma_request_auto = 8, 7.41 + Dma_request_sadc_in = 9, 7.42 + Dma_request_uart4_out = 12, 7.43 + Dma_request_uart4_in = 13, 7.44 + Dma_request_uart3_out = 14, 7.45 + Dma_request_uart3_in = 15, 7.46 + Dma_request_uart2_out = 16, 7.47 + Dma_request_uart2_in = 17, 7.48 + Dma_request_uart1_out = 18, 7.49 + Dma_request_uart1_in = 19, 7.50 + Dma_request_uart0_out = 20, 7.51 + Dma_request_uart0_in = 21, 7.52 + Dma_request_ssi0_out = 22, 7.53 + Dma_request_ssi0_in = 23, 7.54 + Dma_request_ssi1_out = 24, 7.55 + Dma_request_ssi1_in = 25, 7.56 + Dma_request_msc0_out = 26, 7.57 + Dma_request_msc0_in = 27, 7.58 + Dma_request_msc1_out = 28, 7.59 + Dma_request_msc1_in = 29, 7.60 + Dma_request_msc2_out = 30, 7.61 + Dma_request_msc2_in = 31, 7.62 + Dma_request_pcm0_out = 32, 7.63 + Dma_request_pcm0_in = 33, 7.64 + Dma_request_i2c0_out = 36, 7.65 + Dma_request_i2c0_in = 37, 7.66 + Dma_request_i2c1_out = 38, 7.67 + Dma_request_i2c1_in = 39, 7.68 + Dma_request_i2c2_out = 40, 7.69 + Dma_request_i2c2_in = 41, 7.70 + Dma_request_i2c3_out = 42, 7.71 + Dma_request_i2c3_in = 43, 7.72 + Dma_request_i2c4_out = 44, 7.73 + Dma_request_i2c4_in = 45, 7.74 + Dma_request_des_out = 46, 7.75 + Dma_request_des_in = 47, 7.76 +}; 7.77 + 7.78 + 7.79 + 7.80 +#ifdef __cplusplus 7.81 + 7.82 +#include <l4/devices/cpm-jz4780.h> 7.83 +#include <l4/devices/hw_mmio_register_block.h> 7.84 + 7.85 +// Forward declaration. 7.86 + 7.87 +class Dma_jz4780_chip; 7.88 + 7.89 + 7.90 + 7.91 +// DMA channel. 7.92 + 7.93 +class Dma_jz4780_channel 7.94 +{ 7.95 +private: 7.96 + Hw::Register_block<32> _regs; 7.97 + Dma_jz4780_chip *_chip; 7.98 + uint8_t _channel; 7.99 + l4_cap_idx_t _irq = L4_INVALID_CAP; 7.100 + 7.101 +public: 7.102 + Dma_jz4780_channel(Dma_jz4780_chip *chip, uint8_t channel, l4_addr_t start, l4_cap_idx_t irq); 7.103 + 7.104 + unsigned int transfer(uint32_t source, uint32_t destination, 7.105 + unsigned int count, 7.106 + bool source_increment, bool destination_increment, 7.107 + uint8_t source_width, uint8_t destination_width, 7.108 + uint8_t transfer_unit_size, 7.109 + enum Dma_jz4780_request_type type=Dma_request_auto); 7.110 + 7.111 + unsigned int wait(); 7.112 + 7.113 +protected: 7.114 + // Transfer property configuration. 7.115 + 7.116 + uint32_t encode_req_detect_int_length(uint8_t units); 7.117 + 7.118 + uint32_t encode_source_port_width(uint8_t width); 7.119 + 7.120 + uint32_t encode_destination_port_width(uint8_t width); 7.121 + 7.122 + uint32_t encode_transfer_unit_size(uint8_t size); 7.123 + 7.124 + // Transaction control. 7.125 + 7.126 + void ack_irq(); 7.127 + 7.128 + bool completed(); 7.129 + 7.130 + bool error(); 7.131 + 7.132 + bool halted(); 7.133 + 7.134 + bool wait_for_irq(); 7.135 + 7.136 + bool wait_for_irq(unsigned int timeout); 7.137 +}; 7.138 + 7.139 +// DMA device control. 7.140 + 7.141 +class Dma_jz4780_chip 7.142 +{ 7.143 +private: 7.144 + Hw::Register_block<32> _regs; 7.145 + l4_addr_t _start, _end; 7.146 + Cpm_jz4780_chip *_cpm; 7.147 + 7.148 +public: 7.149 + Dma_jz4780_chip(l4_addr_t start, l4_addr_t end, Cpm_jz4780_chip *cpm); 7.150 + 7.151 + void disable(); 7.152 + 7.153 + void enable(); 7.154 + 7.155 + Dma_jz4780_channel *get_channel(uint8_t channel, l4_cap_idx_t irq); 7.156 + 7.157 + // Transaction control. 7.158 + 7.159 + void ack_irq(uint8_t channel); 7.160 + 7.161 + bool error(); 7.162 + 7.163 + bool halted(); 7.164 + 7.165 + bool have_interrupt(uint8_t channel); 7.166 +}; 7.167 + 7.168 +#endif /* __cplusplus */ 7.169 + 7.170 + 7.171 + 7.172 +/* C language interface. */ 7.173 + 7.174 +EXTERN_C_BEGIN 7.175 + 7.176 +void *jz4780_dma_init(l4_addr_t start, l4_addr_t end, void *cpm); 7.177 + 7.178 +void jz4780_dma_disable(void *dma_chip); 7.179 + 7.180 +void jz4780_dma_enable(void *dma_chip); 7.181 + 7.182 +void *jz4780_dma_get_channel(void *dma, uint8_t channel, l4_cap_idx_t irq); 7.183 + 7.184 +unsigned int jz4780_dma_transfer(void *dma_channel, 7.185 + uint32_t source, uint32_t destination, 7.186 + unsigned int count, 7.187 + int source_increment, int destination_increment, 7.188 + uint8_t source_width, uint8_t destination_width, 7.189 + uint8_t transfer_unit_size, 7.190 + enum Dma_jz4780_request_type type); 7.191 + 7.192 +unsigned int jz4780_dma_wait(void *dma_channel); 7.193 + 7.194 +EXTERN_C_END
8.1 --- a/pkg/devices/lib/dma/include/dma-x1600.h Sat Oct 28 01:15:45 2023 +0200 8.2 +++ b/pkg/devices/lib/dma/include/dma-x1600.h Sun Oct 29 16:14:38 2023 +0100 8.3 @@ -30,35 +30,35 @@ 8.4 8.5 enum Dma_x1600_request_type 8.6 { 8.7 - Dma_request_auto = 8, 8.8 - Dma_request_can0_out = 10, 8.9 - Dma_request_can0_in = 11, 8.10 - Dma_request_can1_out = 10, 8.11 - Dma_request_can1_in = 11, 8.12 - Dma_request_uart3_out = 14, 8.13 - Dma_request_uart3_in = 15, 8.14 - Dma_request_uart2_out = 16, 8.15 - Dma_request_uart2_in = 17, 8.16 - Dma_request_uart1_out = 18, 8.17 - Dma_request_uart1_in = 19, 8.18 - Dma_request_uart0_out = 20, 8.19 - Dma_request_uart0_in = 21, 8.20 - Dma_request_ssi0_send_empty = 22, 8.21 - Dma_request_ssi0_recv_full = 23, 8.22 - Dma_request_i2c0_send_empty = 36, 8.23 - Dma_request_i2c0_recv_full = 37, 8.24 - Dma_request_i2c1_send_empty = 38, 8.25 - Dma_request_i2c1_recv_full = 39, 8.26 - Dma_request_ssi_slv_out = 42, 8.27 - Dma_request_ssi_slv_in = 43, 8.28 - Dma_request_msc0_send_empty = 52, 8.29 - Dma_request_msc0_recv_full = 53, 8.30 - Dma_request_msc1_send_empty = 54, 8.31 - Dma_request_msc1_recv_full = 55, 8.32 - Dma_request_sadc_in = 56, 8.33 - Dma_request_aic_loop_out = 61, 8.34 - Dma_request_aic_out = 62, 8.35 - Dma_request_aic_in = 63, 8.36 + Dma_request_auto = 8, 8.37 + Dma_request_can0_out = 10, 8.38 + Dma_request_can0_in = 11, 8.39 + Dma_request_can1_out = 10, 8.40 + Dma_request_can1_in = 11, 8.41 + Dma_request_uart3_out = 14, 8.42 + Dma_request_uart3_in = 15, 8.43 + Dma_request_uart2_out = 16, 8.44 + Dma_request_uart2_in = 17, 8.45 + Dma_request_uart1_out = 18, 8.46 + Dma_request_uart1_in = 19, 8.47 + Dma_request_uart0_out = 20, 8.48 + Dma_request_uart0_in = 21, 8.49 + Dma_request_ssi0_out = 22, 8.50 + Dma_request_ssi0_in = 23, 8.51 + Dma_request_i2c0_out = 36, 8.52 + Dma_request_i2c0_in = 37, 8.53 + Dma_request_i2c1_out = 38, 8.54 + Dma_request_i2c1_in = 39, 8.55 + Dma_request_ssi_slv_out = 42, 8.56 + Dma_request_ssi_slv_in = 43, 8.57 + Dma_request_msc0_out = 52, 8.58 + Dma_request_msc0_in = 53, 8.59 + Dma_request_msc1_out = 54, 8.60 + Dma_request_msc1_in = 55, 8.61 + Dma_request_sadc_in = 56, 8.62 + Dma_request_aic_loop_out = 61, 8.63 + Dma_request_aic_out = 62, 8.64 + Dma_request_aic_in = 63, 8.65 }; 8.66 8.67
9.1 --- a/pkg/devices/lib/dma/src/Makefile Sat Oct 28 01:15:45 2023 +0200 9.2 +++ b/pkg/devices/lib/dma/src/Makefile Sun Oct 29 16:14:38 2023 +0100 9.3 @@ -4,7 +4,7 @@ 9.4 TARGET = libdma.o.a libdma.o.so 9.5 PC_FILENAME := libdrivers-dma 9.6 9.7 -SRC_CC := jz4730.cc x1600.cc 9.8 +SRC_CC := jz4730.cc jz4780.cc x1600.cc 9.9 9.10 PRIVATE_INCDIR += $(PKGDIR)/lib/dma/include 9.11
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/pkg/devices/lib/dma/src/jz4780.cc Sun Oct 29 16:14:38 2023 +0100 10.3 @@ -0,0 +1,520 @@ 10.4 +/* 10.5 + * DMA support for the JZ4780. 10.6 + * NOTE: This should be combined with the X1600 support. 10.7 + * 10.8 + * Copyright (C) 2021, 2023 Paul Boddie <paul@boddie.org.uk> 10.9 + * 10.10 + * This program is free software; you can redistribute it and/or 10.11 + * modify it under the terms of the GNU General Public License as 10.12 + * published by the Free Software Foundation; either version 2 of 10.13 + * the License, or (at your option) any later version. 10.14 + * 10.15 + * This program is distributed in the hope that it will be useful, 10.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10.18 + * GNU General Public License for more details. 10.19 + * 10.20 + * You should have received a copy of the GNU General Public License 10.21 + * along with this program; if not, write to the Free Software 10.22 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 10.23 + * Boston, MA 02110-1301, USA 10.24 + */ 10.25 + 10.26 +#include <l4/devices/dma-jz4780.h> 10.27 +#include <l4/devices/hw_mmio_register_block.h> 10.28 + 10.29 +#include <l4/sys/icu.h> 10.30 +#include <l4/sys/ipc.h> 10.31 +#include <l4/sys/irq.h> 10.32 +#include <l4/util/util.h> 10.33 + 10.34 +#include <stdio.h> 10.35 + 10.36 + 10.37 + 10.38 +enum Global_regs 10.39 +{ 10.40 + Dma_control = 0x1000, // DMAC 10.41 + Dma_irq_pending = 0x1004, // DIRQP 10.42 +}; 10.43 + 10.44 +enum Channel_regs 10.45 +{ 10.46 + Dma_source = 0x00, // DSA 10.47 + Dma_destination = 0x04, // DTA 10.48 + Dma_transfer_count = 0x08, // DTC 10.49 + Dma_request_source = 0x0c, // DRT 10.50 + Dma_control_status = 0x10, // DCS 10.51 + Dma_command = 0x14, // DCM 10.52 + Dma_descriptor_address = 0x18, // DDA 10.53 + Dma_stride = 0x1c, // DSD 10.54 +}; 10.55 + 10.56 +enum Dma_control_bits : unsigned 10.57 +{ 10.58 + Dma_fast_msc_transfer = 0x80000000, // FMSC 10.59 + Dma_fast_ssi_transfer = 0x40000000, // FSSI 10.60 + Dma_fast_tssi_transfer = 0x20000000, // FTSSI 10.61 + Dma_fast_uart_transfer = 0x10000000, // FUART 10.62 + Dma_fast_aic_transfer = 0x08000000, // FAIC 10.63 + 10.64 + Dma_intc_irq_channel_mask = 0x003e0000, // INTCC 10.65 + Dma_intc_irq_channel_bind = 0x00010000, // INTCE 10.66 + 10.67 + Dma_control_trans_halted = 0x00000008, // HLT 10.68 + Dma_control_address_error = 0x00000004, // AR 10.69 + Dma_control_special_ch01 = 0x00000002, // CH01 10.70 + Dma_control_enable = 0x00000001, // DMAE 10.71 +}; 10.72 + 10.73 +enum Dma_transfer_count_bits : unsigned 10.74 +{ 10.75 + Dma_transfer_count_mask = 0x00ffffff, 10.76 +}; 10.77 + 10.78 +enum Dma_request_source_bits : unsigned 10.79 +{ 10.80 + Dma_request_type_mask = 0x0000003f, 10.81 +}; 10.82 + 10.83 +enum Dma_control_status_bits : unsigned 10.84 +{ 10.85 + Dma_no_descriptor_transfer = 0x80000000, 10.86 + Dma_8word_descriptor = 0x40000000, 10.87 + Dma_copy_offset_mask = 0x0000ff00, 10.88 + Dma_address_error = 0x00000010, 10.89 + Dma_trans_completed = 0x00000008, 10.90 + Dma_trans_halted = 0x00000004, 10.91 + Dma_channel_enable = 0x00000001, 10.92 + 10.93 + Dma_copy_offset_shift = 8, 10.94 +}; 10.95 + 10.96 +enum Dma_command_bits : unsigned 10.97 +{ 10.98 + Dma_special_source_mask = 0x0c000000, 10.99 + Dma_special_source_tcsm = 0x00000000, 10.100 + Dma_special_source_bch_nemc = 0x04000000, 10.101 + Dma_special_source_reserved_ddr = 0x08000000, 10.102 + 10.103 + Dma_special_destination_mask = 0x03000000, 10.104 + Dma_special_destination_tcsm = 0x00000000, 10.105 + Dma_special_destination_bch_nemc = 0x01000000, 10.106 + Dma_special_destination_reserved_ddr = 0x02000000, 10.107 + 10.108 + Dma_source_address_increment = 0x00800000, 10.109 + Dma_source_address_no_increment = 0x00000000, 10.110 + Dma_destination_address_increment = 0x00400000, 10.111 + Dma_destination_address_no_increment = 0x00000000, 10.112 + 10.113 + Dma_recommended_data_unit_size_mask = 0x000f0000, 10.114 + Dma_source_port_width_mask = 0x0000c000, 10.115 + Dma_destination_port_width_mask = 0x00003000, 10.116 + Dma_transfer_unit_size_mask = 0x00000f00, 10.117 + 10.118 + Dma_trans_unit_size_32_bit = 0x00000000, 10.119 + Dma_trans_unit_size_8_bit = 0x00000100, 10.120 + Dma_trans_unit_size_16_bit = 0x00000200, 10.121 + Dma_trans_unit_size_16_byte = 0x00000300, 10.122 + Dma_trans_unit_size_32_byte = 0x00000400, 10.123 + Dma_trans_unit_size_64_byte = 0x00000500, 10.124 + Dma_trans_unit_size_128_byte = 0x00000600, 10.125 + Dma_trans_unit_size_autonomous = 0x00000700, 10.126 + 10.127 + Dma_stride_enable = 0x00000004, 10.128 + Dma_transfer_irq_enable = 0x00000002, 10.129 + Dma_descriptor_link_enable = 0x00000001, 10.130 + 10.131 + Dma_recommended_data_unit_size_shift = 16, 10.132 + Dma_source_port_width_shift = 14, 10.133 + Dma_destination_port_width_shift = 12, 10.134 + Dma_transfer_unit_size_shift = 8, 10.135 +}; 10.136 + 10.137 +enum Dma_port_width_values : unsigned 10.138 +{ 10.139 + Dma_port_width_32_bit = 0, 10.140 + Dma_port_width_8_bit = 1, 10.141 + Dma_port_width_16_bit = 2, 10.142 +}; 10.143 + 10.144 + 10.145 + 10.146 +// Initialise a channel. 10.147 + 10.148 +Dma_jz4780_channel::Dma_jz4780_channel(Dma_jz4780_chip *chip, uint8_t channel, 10.149 + l4_addr_t start, l4_cap_idx_t irq) 10.150 +: _chip(chip), _channel(channel), _irq(irq) 10.151 +{ 10.152 + _regs = new Hw::Mmio_register_block<32>(start); 10.153 + 10.154 + // Initialise the transfer count. 10.155 + 10.156 + _regs[Dma_transfer_count] = 0; 10.157 +} 10.158 + 10.159 +// Return the closest interval length greater than or equal to the number of 10.160 +// units given encoded in the request detection interval length field of the 10.161 +// control/status register. 10.162 + 10.163 +uint32_t 10.164 +Dma_jz4780_channel::encode_req_detect_int_length(uint8_t units) 10.165 +{ 10.166 + static uint8_t lengths[] = {0, 1, 2, 3, 4, 8, 16, 32, 64, 128}; 10.167 + int i; 10.168 + 10.169 + if (!units) 10.170 + return 0; 10.171 + 10.172 + for (i = 0; i <= 9; i++) 10.173 + { 10.174 + if (lengths[i] >= units) 10.175 + break; 10.176 + } 10.177 + 10.178 + return i << Dma_recommended_data_unit_size_shift; 10.179 +} 10.180 + 10.181 +// Encode the appropriate source port width for the given request type. 10.182 + 10.183 +uint32_t 10.184 +Dma_jz4780_channel::encode_source_port_width(uint8_t width) 10.185 +{ 10.186 + switch (width) 10.187 + { 10.188 + case 1: 10.189 + return Dma_port_width_8_bit << Dma_source_port_width_shift; 10.190 + 10.191 + case 2: 10.192 + return Dma_port_width_16_bit << Dma_source_port_width_shift; 10.193 + 10.194 + default: 10.195 + return Dma_port_width_32_bit << Dma_source_port_width_shift; 10.196 + } 10.197 +} 10.198 + 10.199 +// Encode the appropriate destination port width for the given request type. 10.200 + 10.201 +uint32_t 10.202 +Dma_jz4780_channel::encode_destination_port_width(uint8_t width) 10.203 +{ 10.204 + switch (width) 10.205 + { 10.206 + case 1: 10.207 + return Dma_port_width_8_bit << Dma_destination_port_width_shift; 10.208 + 10.209 + case 2: 10.210 + return Dma_port_width_16_bit << Dma_destination_port_width_shift; 10.211 + 10.212 + default: 10.213 + return Dma_port_width_32_bit << Dma_destination_port_width_shift; 10.214 + } 10.215 +} 10.216 + 10.217 +// Encode the transfer unit size. 10.218 +// NOTE: This does not handle the external case. 10.219 + 10.220 +uint32_t 10.221 +Dma_jz4780_channel::encode_transfer_unit_size(uint8_t size) 10.222 +{ 10.223 + switch (size) 10.224 + { 10.225 + case 0: 10.226 + return Dma_trans_unit_size_autonomous; 10.227 + 10.228 + case 1: 10.229 + return Dma_trans_unit_size_8_bit; 10.230 + 10.231 + case 2: 10.232 + return Dma_trans_unit_size_16_bit; 10.233 + 10.234 + case 16: 10.235 + return Dma_trans_unit_size_16_byte; 10.236 + 10.237 + case 32: 10.238 + return Dma_trans_unit_size_32_byte; 10.239 + 10.240 + case 64: 10.241 + return Dma_trans_unit_size_64_byte; 10.242 + 10.243 + case 128: 10.244 + return Dma_trans_unit_size_128_byte; 10.245 + 10.246 + default: 10.247 + return Dma_trans_unit_size_32_bit; 10.248 + } 10.249 +} 10.250 + 10.251 +// Transfer data between memory locations. 10.252 + 10.253 +unsigned int 10.254 +Dma_jz4780_channel::transfer(uint32_t source, uint32_t destination, 10.255 + unsigned int count, 10.256 + bool source_increment, bool destination_increment, 10.257 + uint8_t source_width, uint8_t destination_width, 10.258 + uint8_t transfer_unit_size, 10.259 + enum Dma_jz4780_request_type type) 10.260 +{ 10.261 + printf("transfer:%s%s%s%s\n", error() ? " error" : "", 10.262 + halted() ? " halted" : "", 10.263 + completed() ? " completed" : "", 10.264 + _regs[Dma_transfer_count] ? " count" : ""); 10.265 + 10.266 + // Ensure an absence of address error and halt conditions globally and in this channel. 10.267 + 10.268 + if (error() || halted()) 10.269 + return 0; 10.270 + 10.271 + // Ensure an absence of transaction completed and zero transfer count for this channel. 10.272 + 10.273 + if (completed() || _regs[Dma_transfer_count]) 10.274 + return 0; 10.275 + 10.276 + // Disable the channel. 10.277 + 10.278 + _regs[Dma_control_status] = _regs[Dma_control_status] & ~Dma_channel_enable; 10.279 + 10.280 + // Set addresses. 10.281 + 10.282 + _regs[Dma_source] = source; 10.283 + _regs[Dma_destination] = destination; 10.284 + 10.285 + // Set transfer count to the number of units. 10.286 + 10.287 + unsigned int units = count < Dma_transfer_count_mask ? count : Dma_transfer_count_mask; 10.288 + 10.289 + _regs[Dma_transfer_count] = units; 10.290 + 10.291 + // Set auto-request for memory-to-memory transfers. Otherwise, set the 10.292 + // indicated request type. 10.293 + 10.294 + _regs[Dma_request_source] = type; 10.295 + 10.296 + // For a descriptor, the actual fields would be populated instead of the 10.297 + // command register, descriptor transfer would be indicated in the control/ 10.298 + // status register along with the appropriate descriptor size indicator. 10.299 + 10.300 + /* NOTE: To be considered... 10.301 + * request detection interval length (for autonomous mode) 10.302 + */ 10.303 + 10.304 + _regs[Dma_command] = (source_increment ? Dma_source_address_increment : Dma_source_address_no_increment) | 10.305 + (destination_increment ? Dma_destination_address_increment : Dma_destination_address_no_increment) | 10.306 + encode_source_port_width(source_width) | 10.307 + encode_destination_port_width(destination_width) | 10.308 + encode_transfer_unit_size(transfer_unit_size) | 10.309 + Dma_transfer_irq_enable; 10.310 + 10.311 + // For a descriptor, the descriptor address would be set and the doorbell 10.312 + // register field for the channel set. 10.313 + 10.314 + // Enable the channel (and peripheral). 10.315 + 10.316 + _regs[Dma_control_status] = Dma_no_descriptor_transfer | 10.317 + Dma_channel_enable; 10.318 + 10.319 + // Return the number of units to transfer. 10.320 + 10.321 + return units; 10.322 +} 10.323 + 10.324 +unsigned int 10.325 +Dma_jz4780_channel::wait() 10.326 +{ 10.327 + // An interrupt will occur upon completion, the completion flag will be set 10.328 + // and the transfer count will be zero. 10.329 + 10.330 + unsigned int remaining = 0; 10.331 + 10.332 + do 10.333 + { 10.334 + if (!wait_for_irq(1000000)) 10.335 + printf("status = %x\n", (uint32_t) _regs[Dma_control_status]); 10.336 + else 10.337 + { 10.338 + printf("status = %x\n", (uint32_t) _regs[Dma_control_status]); 10.339 + remaining = _regs[Dma_transfer_count]; 10.340 + ack_irq(); 10.341 + break; 10.342 + } 10.343 + } 10.344 + while (!error() && !halted() && !completed()); 10.345 + 10.346 + // Reset the channel status. 10.347 + 10.348 + _regs[Dma_control_status] = _regs[Dma_control_status] & ~(Dma_channel_enable | 10.349 + Dma_trans_completed | Dma_address_error | 10.350 + Dma_trans_halted); 10.351 + _regs[Dma_transfer_count] = 0; 10.352 + 10.353 + // Return the number of remaining units. 10.354 + 10.355 + return remaining; 10.356 +} 10.357 + 10.358 +// Wait indefinitely for an interrupt request, returning true if one was delivered. 10.359 + 10.360 +bool 10.361 +Dma_jz4780_channel::wait_for_irq() 10.362 +{ 10.363 + return !l4_error(l4_irq_receive(_irq, L4_IPC_NEVER)) && _chip->have_interrupt(_channel); 10.364 +} 10.365 + 10.366 +// Wait up to the given timeout (in microseconds) for an interrupt request, 10.367 +// returning true if one was delivered. 10.368 + 10.369 +bool 10.370 +Dma_jz4780_channel::wait_for_irq(unsigned int timeout) 10.371 +{ 10.372 + return !l4_error(l4_irq_receive(_irq, l4_timeout(L4_IPC_TIMEOUT_NEVER, l4util_micros2l4to(timeout)))) && _chip->have_interrupt(_channel); 10.373 +} 10.374 + 10.375 +// Acknowledge an interrupt condition. 10.376 + 10.377 +void 10.378 +Dma_jz4780_channel::ack_irq() 10.379 +{ 10.380 + _chip->ack_irq(_channel); 10.381 +} 10.382 + 10.383 +// Return whether a transfer has completed. 10.384 + 10.385 +bool 10.386 +Dma_jz4780_channel::completed() 10.387 +{ 10.388 + return _regs[Dma_control_status] & Dma_trans_completed ? true : false; 10.389 +} 10.390 + 10.391 +// Return whether an address error condition has arisen. 10.392 + 10.393 +bool 10.394 +Dma_jz4780_channel::error() 10.395 +{ 10.396 + return _chip->error() || (_regs[Dma_control_status] & Dma_address_error ? true : false); 10.397 +} 10.398 + 10.399 +// Return whether a transfer has halted. 10.400 + 10.401 +bool 10.402 +Dma_jz4780_channel::halted() 10.403 +{ 10.404 + return _chip->halted() || (_regs[Dma_control_status] & Dma_trans_halted ? true : false); 10.405 +} 10.406 + 10.407 + 10.408 + 10.409 +// Initialise the I2C controller. 10.410 + 10.411 +Dma_jz4780_chip::Dma_jz4780_chip(l4_addr_t start, l4_addr_t end, 10.412 + Cpm_jz4780_chip *cpm) 10.413 +: _start(start), _end(end), _cpm(cpm) 10.414 +{ 10.415 + _regs = new Hw::Mmio_register_block<32>(start); 10.416 +} 10.417 + 10.418 +// Enable the peripheral. 10.419 + 10.420 +void 10.421 +Dma_jz4780_chip::enable() 10.422 +{ 10.423 + // Make sure that the DMA clock is available. 10.424 + 10.425 + _cpm->start_clock(Clock_dma); 10.426 + 10.427 + _regs[Dma_control] = Dma_control_enable; 10.428 + while (!(_regs[Dma_control] & Dma_control_enable)); 10.429 +} 10.430 + 10.431 +// Disable the channel. 10.432 + 10.433 +void 10.434 +Dma_jz4780_chip::disable() 10.435 +{ 10.436 + _regs[Dma_control] = 0; 10.437 + while (_regs[Dma_control] & Dma_control_enable); 10.438 +} 10.439 + 10.440 +// Obtain a channel object. 10.441 + 10.442 +Dma_jz4780_channel * 10.443 +Dma_jz4780_chip::get_channel(uint8_t channel, l4_cap_idx_t irq) 10.444 +{ 10.445 + if (channel < 32) 10.446 + return new Dma_jz4780_channel(this, channel, _start + 0x20 * channel, irq); 10.447 + else 10.448 + throw -L4_EINVAL; 10.449 +} 10.450 + 10.451 +// Return whether an interrupt is pending on the given channel. 10.452 + 10.453 +bool 10.454 +Dma_jz4780_chip::have_interrupt(uint8_t channel) 10.455 +{ 10.456 + return _regs[Dma_irq_pending] & (1 << channel) ? true : false; 10.457 +} 10.458 + 10.459 +// Acknowledge an interrupt condition on the given channel. 10.460 + 10.461 +void 10.462 +Dma_jz4780_chip::ack_irq(uint8_t channel) 10.463 +{ 10.464 + _regs[Dma_irq_pending] = _regs[Dma_irq_pending] & ~(1 << channel); 10.465 +} 10.466 + 10.467 +// Return whether an address error condition has arisen. 10.468 + 10.469 +bool 10.470 +Dma_jz4780_chip::error() 10.471 +{ 10.472 + return _regs[Dma_control] & Dma_control_address_error ? true : false; 10.473 +} 10.474 + 10.475 +// Return whether a transfer has halted. 10.476 + 10.477 +bool 10.478 +Dma_jz4780_chip::halted() 10.479 +{ 10.480 + return _regs[Dma_control] & Dma_control_trans_halted ? true : false; 10.481 +} 10.482 + 10.483 + 10.484 + 10.485 +// C language interface functions. 10.486 + 10.487 +void *jz4780_dma_init(l4_addr_t start, l4_addr_t end, void *cpm) 10.488 +{ 10.489 + return (void *) new Dma_jz4780_chip(start, end, static_cast<Cpm_jz4780_chip *>(cpm)); 10.490 +} 10.491 + 10.492 +void jz4780_dma_disable(void *dma_chip) 10.493 +{ 10.494 + static_cast<Dma_jz4780_chip *>(dma_chip)->disable(); 10.495 +} 10.496 + 10.497 +void jz4780_dma_enable(void *dma_chip) 10.498 +{ 10.499 + static_cast<Dma_jz4780_chip *>(dma_chip)->enable(); 10.500 +} 10.501 + 10.502 +void *jz4780_dma_get_channel(void *dma, uint8_t channel, l4_cap_idx_t irq) 10.503 +{ 10.504 + return static_cast<Dma_jz4780_chip *>(dma)->get_channel(channel, irq); 10.505 +} 10.506 + 10.507 +unsigned int jz4780_dma_transfer(void *dma_channel, 10.508 + uint32_t source, uint32_t destination, 10.509 + unsigned int count, 10.510 + int source_increment, int destination_increment, 10.511 + uint8_t source_width, uint8_t destination_width, 10.512 + uint8_t transfer_unit_size, 10.513 + enum Dma_jz4780_request_type type) 10.514 +{ 10.515 + return static_cast<Dma_jz4780_channel *>(dma_channel)->transfer(source, 10.516 + destination, count, source_increment, destination_increment, source_width, 10.517 + destination_width, transfer_unit_size, type); 10.518 +} 10.519 + 10.520 +unsigned int jz4780_dma_wait(void *dma_channel) 10.521 +{ 10.522 + return static_cast<Dma_jz4780_channel *>(dma_channel)->wait(); 10.523 +}
11.1 --- a/pkg/devices/lib/dma/src/x1600.cc Sat Oct 28 01:15:45 2023 +0200 11.2 +++ b/pkg/devices/lib/dma/src/x1600.cc Sun Oct 29 16:14:38 2023 +0100 11.3 @@ -68,7 +68,7 @@ 11.4 11.5 enum Dma_request_source_bits : unsigned 11.6 { 11.7 - Dma_request_type_mask = 0x0000001f, 11.8 + Dma_request_type_mask = 0x0000003f, 11.9 }; 11.10 11.11 enum Dma_control_status_bits : unsigned
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/pkg/devices/lib/i2c/include/i2c-common.h Sun Oct 29 16:14:38 2023 +0100 12.3 @@ -0,0 +1,123 @@ 12.4 +/* 12.5 + * I2C support for the JZ4780 and X1600. 12.6 + * 12.7 + * Copyright (C) 2017, 2018, 2019, 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 +#pragma once 12.26 + 12.27 +#include <l4/sys/types.h> 12.28 +#include <stdint.h> 12.29 + 12.30 + 12.31 + 12.32 +#ifdef __cplusplus 12.33 + 12.34 +#include <l4/devices/cpm.h> 12.35 +#include <l4/devices/hw_mmio_register_block.h> 12.36 + 12.37 +// I2C channel. 12.38 + 12.39 +class I2c_channel 12.40 +{ 12.41 +protected: 12.42 + Hw::Register_block<32> _regs; 12.43 + Cpm_chip *_cpm; 12.44 + uint32_t _frequency; 12.45 + 12.46 + // Buffer management. 12.47 + 12.48 + unsigned int _pos, _reqpos, _total; 12.49 + uint8_t *_buf; 12.50 + 12.51 + // Status conditions. 12.52 + 12.53 + int _fail; 12.54 + int _stop; 12.55 + 12.56 + // Common operations. 12.57 + 12.58 + void enable(); 12.59 + 12.60 + int active(); 12.61 + int have_input(); 12.62 + int have_output(); 12.63 + int can_send(); 12.64 + 12.65 + void reset_flags(); 12.66 + void init_parameters(); 12.67 + void set_frequency(); 12.68 + 12.69 + void set_read_threshold(); 12.70 + void queue_reads(); 12.71 + void queue_writes(); 12.72 + void store_reads(); 12.73 + 12.74 +public: 12.75 + explicit I2c_channel(l4_addr_t start, enum Clock_identifiers clock, 12.76 + Cpm_chip *cpm, uint32_t frequency); 12.77 + 12.78 + uint32_t get_frequency(); 12.79 + void set_target(uint8_t addr); 12.80 + 12.81 + // Reading initiation and execution. 12.82 + 12.83 + void start_read(uint8_t buf[], unsigned int total, int stop = 0); 12.84 + void read(); 12.85 + 12.86 + // Writing initiation and execution. 12.87 + 12.88 + void start_write(uint8_t buf[], unsigned int total, int stop = 0); 12.89 + void write(); 12.90 + 12.91 + // Transaction control. 12.92 + 12.93 + void stop(); 12.94 + void disable(); 12.95 + 12.96 + // Specific status conditions. 12.97 + 12.98 + unsigned int have_read(); 12.99 + unsigned int have_written(); 12.100 + int read_done(); 12.101 + int write_done(); 12.102 + 12.103 + int failed(); 12.104 + int read_failed(); 12.105 + int write_failed(); 12.106 +}; 12.107 + 12.108 +// I2C device control. 12.109 + 12.110 +class I2c_chip 12.111 +{ 12.112 +protected: 12.113 + l4_addr_t _start, _end; 12.114 + Cpm_chip *_cpm; 12.115 + uint32_t _frequency; 12.116 + 12.117 + virtual unsigned int num_channels() = 0; 12.118 + 12.119 +public: 12.120 + explicit I2c_chip(l4_addr_t start, l4_addr_t end, Cpm_chip *cpm, 12.121 + uint32_t frequency); 12.122 + 12.123 + I2c_channel *get_channel(uint8_t channel); 12.124 +}; 12.125 + 12.126 +#endif /* __cplusplus */
13.1 --- a/pkg/devices/lib/i2c/include/i2c-jz4780.h Sat Oct 28 01:15:45 2023 +0200 13.2 +++ b/pkg/devices/lib/i2c/include/i2c-jz4780.h Sun Oct 29 16:14:38 2023 +0100 13.3 @@ -28,91 +28,28 @@ 13.4 13.5 #ifdef __cplusplus 13.6 13.7 -#include <l4/devices/cpm-jz4780.h> 13.8 -#include <l4/devices/hw_mmio_register_block.h> 13.9 +#include <l4/devices/i2c-common.h> 13.10 13.11 // I2C channel. 13.12 13.13 -class I2c_jz4780_channel 13.14 +class I2c_jz4780_channel : public I2c_channel 13.15 { 13.16 -private: 13.17 - Hw::Register_block<32> _regs; 13.18 - Cpm_jz4780_chip *_cpm; 13.19 - uint32_t _frequency; 13.20 - 13.21 - // Buffer management. 13.22 - 13.23 - unsigned int _pos, _reqpos, _total; 13.24 - uint8_t *_buf; 13.25 - 13.26 - // Status conditions. 13.27 - 13.28 - int _fail; 13.29 - 13.30 public: 13.31 - I2c_jz4780_channel(l4_addr_t start, Cpm_jz4780_chip *cpm, 13.32 - uint32_t frequency); 13.33 - 13.34 - void set_target(uint8_t addr); 13.35 - 13.36 - // Reading initiation and execution. 13.37 - 13.38 - void start_read(uint8_t buf[], unsigned int total); 13.39 - void read(); 13.40 - 13.41 - // Writing initiation and execution. 13.42 - 13.43 - void start_write(uint8_t buf[], unsigned int total); 13.44 - void write(); 13.45 - 13.46 - // Transaction control. 13.47 - 13.48 - void stop(); 13.49 - void disable(); 13.50 - 13.51 - // Specific status conditions. 13.52 - 13.53 - unsigned int have_read(); 13.54 - unsigned int have_written(); 13.55 - int read_done(); 13.56 - int write_done(); 13.57 - 13.58 - int failed(); 13.59 - int read_failed(); 13.60 - int write_failed(); 13.61 - 13.62 -private: 13.63 - void enable(); 13.64 - 13.65 - int active(); 13.66 - int have_input(); 13.67 - int have_output(); 13.68 - int can_send(); 13.69 - 13.70 - void reset_flags(); 13.71 - void init_parameters(); 13.72 - void set_frequency(); 13.73 - 13.74 - void set_read_threshold(); 13.75 - void queue_reads(); 13.76 - void queue_writes(); 13.77 - void store_reads(); 13.78 + explicit I2c_jz4780_channel(l4_addr_t start, enum Clock_identifiers clock, 13.79 + Cpm_chip *cpm, uint32_t frequency); 13.80 }; 13.81 13.82 // I2C device control. 13.83 13.84 -class I2c_jz4780_chip 13.85 +class I2c_jz4780_chip : public I2c_chip 13.86 { 13.87 -private: 13.88 - l4_addr_t _start, _end; 13.89 - Cpm_jz4780_chip *_cpm; 13.90 - uint32_t _frequency; 13.91 +protected: 13.92 + unsigned int num_channels() 13.93 + { return 5; } 13.94 13.95 public: 13.96 - I2c_jz4780_chip(l4_addr_t start, l4_addr_t end, Cpm_jz4780_chip *cpm, 13.97 - uint32_t frequency); 13.98 - 13.99 - I2c_jz4780_channel *get_channel(uint8_t channel); 13.100 + explicit I2c_jz4780_chip(l4_addr_t start, l4_addr_t end, Cpm_chip *cpm, 13.101 + uint32_t frequency); 13.102 }; 13.103 13.104 #endif /* __cplusplus */ 13.105 @@ -126,17 +63,19 @@ 13.106 void *jz4780_i2c_init(l4_addr_t start, l4_addr_t end, void *cpm, 13.107 uint32_t frequency); 13.108 13.109 -void jz4780_i2c_disable(void *i2c_channel); 13.110 +void *jz4780_i2c_get_channel(void *i2c, uint8_t channel); 13.111 13.112 -void *jz4780_i2c_get_channel(void *i2c, uint8_t channel); 13.113 +uint32_t jz4780_i2c_get_frequency(void *i2c_channel); 13.114 13.115 void jz4780_i2c_set_target(void *i2c_channel, uint8_t addr); 13.116 13.117 -void jz4780_i2c_start_read(void *i2c_channel, uint8_t buf[], unsigned int total); 13.118 +void jz4780_i2c_start_read(void *i2c_channel, uint8_t buf[], unsigned int total, 13.119 + int stop); 13.120 13.121 void jz4780_i2c_read(void *i2c_channel); 13.122 13.123 -void jz4780_i2c_start_write(void *i2c_channel, uint8_t buf[], unsigned int total); 13.124 +void jz4780_i2c_start_write(void *i2c_channel, uint8_t buf[], unsigned int total, 13.125 + int stop); 13.126 13.127 void jz4780_i2c_write(void *i2c_channel); 13.128 13.129 @@ -150,6 +89,4 @@ 13.130 13.131 int jz4780_i2c_failed(void *i2c_channel); 13.132 13.133 -void jz4780_i2c_stop(void *i2c_channel); 13.134 - 13.135 EXTERN_C_END
14.1 --- a/pkg/devices/lib/i2c/include/i2c-x1600.h Sat Oct 28 01:15:45 2023 +0200 14.2 +++ b/pkg/devices/lib/i2c/include/i2c-x1600.h Sun Oct 29 16:14:38 2023 +0100 14.3 @@ -28,93 +28,28 @@ 14.4 14.5 #ifdef __cplusplus 14.6 14.7 -#include <l4/devices/cpm-x1600.h> 14.8 -#include <l4/devices/hw_mmio_register_block.h> 14.9 +#include <l4/devices/i2c-common.h> 14.10 14.11 // I2C channel. 14.12 14.13 -class I2c_x1600_channel 14.14 +class I2c_x1600_channel : public I2c_channel 14.15 { 14.16 -private: 14.17 - Hw::Register_block<32> _regs; 14.18 - Cpm_x1600_chip *_cpm; 14.19 - uint32_t _frequency; 14.20 - 14.21 - // Buffer management. 14.22 - 14.23 - unsigned int _pos, _reqpos, _total; 14.24 - uint8_t *_buf; 14.25 - 14.26 - // Status conditions. 14.27 - 14.28 - int _fail; 14.29 - int _stop; 14.30 - 14.31 public: 14.32 - I2c_x1600_channel(l4_addr_t start, enum Clock_identifiers clock, 14.33 - Cpm_x1600_chip *cpm, uint32_t frequency); 14.34 - 14.35 - uint32_t get_frequency(); 14.36 - void set_target(uint8_t addr); 14.37 - 14.38 - // Reading initiation and execution. 14.39 - 14.40 - void start_read(uint8_t buf[], unsigned int total, int stop = 0); 14.41 - void read(); 14.42 - 14.43 - // Writing initiation and execution. 14.44 - 14.45 - void start_write(uint8_t buf[], unsigned int total, int stop = 0); 14.46 - void write(); 14.47 - 14.48 - // Transaction control. 14.49 - 14.50 - void stop(); 14.51 - void disable(); 14.52 - 14.53 - // Specific status conditions. 14.54 - 14.55 - unsigned int have_read(); 14.56 - unsigned int have_written(); 14.57 - int read_done(); 14.58 - int write_done(); 14.59 - 14.60 - int failed(); 14.61 - int read_failed(); 14.62 - int write_failed(); 14.63 - 14.64 -private: 14.65 - void enable(); 14.66 - 14.67 - int active(); 14.68 - int have_input(); 14.69 - int have_output(); 14.70 - int can_send(); 14.71 - 14.72 - void reset_flags(); 14.73 - void init_parameters(); 14.74 - void set_frequency(); 14.75 - 14.76 - void set_read_threshold(); 14.77 - void queue_reads(); 14.78 - void queue_writes(); 14.79 - void store_reads(); 14.80 + explicit I2c_x1600_channel(l4_addr_t start, enum Clock_identifiers clock, 14.81 + Cpm_chip *cpm, uint32_t frequency); 14.82 }; 14.83 14.84 // I2C device control. 14.85 14.86 -class I2c_x1600_chip 14.87 +class I2c_x1600_chip : public I2c_chip 14.88 { 14.89 -private: 14.90 - l4_addr_t _start, _end; 14.91 - Cpm_x1600_chip *_cpm; 14.92 - uint32_t _frequency; 14.93 +protected: 14.94 + unsigned int num_channels() 14.95 + { return 2; } 14.96 14.97 public: 14.98 - I2c_x1600_chip(l4_addr_t start, l4_addr_t end, Cpm_x1600_chip *cpm, 14.99 - uint32_t frequency); 14.100 - 14.101 - I2c_x1600_channel *get_channel(uint8_t channel); 14.102 + explicit I2c_x1600_chip(l4_addr_t start, l4_addr_t end, Cpm_chip *cpm, 14.103 + uint32_t frequency); 14.104 }; 14.105 14.106 #endif /* __cplusplus */
15.1 --- a/pkg/devices/lib/i2c/src/Makefile Sat Oct 28 01:15:45 2023 +0200 15.2 +++ b/pkg/devices/lib/i2c/src/Makefile Sun Oct 29 16:14:38 2023 +0100 15.3 @@ -4,7 +4,7 @@ 15.4 TARGET = libi2c.o.a libi2c.o.so 15.5 PC_FILENAME := libdrivers-i2c 15.6 15.7 -SRC_CC := jz4730.cc jz4780.cc x1600.cc gpio.cc 15.8 +SRC_CC := common.cc jz4730.cc jz4780.cc x1600.cc gpio.cc 15.9 15.10 PRIVATE_INCDIR += $(PKGDIR)/lib/i2c/include 15.11
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/pkg/devices/lib/i2c/src/common.cc Sun Oct 29 16:14:38 2023 +0100 16.3 @@ -0,0 +1,706 @@ 16.4 +/* 16.5 + * I2C support for the JZ4780 and X1600. 16.6 + * 16.7 + * Copyright (C) 2017, 2018, 2021, 2023 Paul Boddie <paul@boddie.org.uk> 16.8 + * 16.9 + * This program is free software; you can redistribute it and/or 16.10 + * modify it under the terms of the GNU General Public License as 16.11 + * published by the Free Software Foundation; either version 2 of 16.12 + * the License, or (at your option) any later version. 16.13 + * 16.14 + * This program is distributed in the hope that it will be useful, 16.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 16.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16.17 + * GNU General Public License for more details. 16.18 + * 16.19 + * You should have received a copy of the GNU General Public License 16.20 + * along with this program; if not, write to the Free Software 16.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 16.22 + * Boston, MA 02110-1301, USA 16.23 + */ 16.24 + 16.25 +#include <l4/devices/i2c-common.h> 16.26 + 16.27 +#include <l4/sys/icu.h> 16.28 +#include <l4/util/util.h> 16.29 +#include <sys/time.h> 16.30 + 16.31 +/* NOTE: The X1600 is very similar to the JZ4780 with the registers 16.32 + renamed to I2C from SMB, with a few high speed registers, the 16.33 + I2C_RINTST, I2C_TXFLR and I2C_RXFLR registers, and a few other 16.34 + registers added, with I2C_SDAHD appearing at a different location. */ 16.35 + 16.36 +enum Regs 16.37 +{ 16.38 + I2c_control = 0x000, // I2C_CON 16.39 + I2c_target_address = 0x004, // I2C_TAR 16.40 + I2c_slave_address = 0x008, // I2C_SAR 16.41 + I2c_master_code = 0x00c, // I2C_HS_MADDR 16.42 + I2c_data_command = 0x010, // I2C_DC 16.43 + Std_high_count = 0x014, // I2C_SHCNT 16.44 + Std_low_count = 0x018, // I2C_SLCNT 16.45 + Fast_high_count = 0x01c, // I2C_FHCNT 16.46 + Fast_low_count = 0x020, // I2C_FLCNT 16.47 + Int_status = 0x02c, // I2C_INTST (read-only) 16.48 + Int_mask = 0x030, // I2C_INTM 16.49 + Rx_fifo_thold = 0x038, // I2C_RXTL 16.50 + Tx_fifo_thold = 0x03c, // I2C_TXTL 16.51 + Int_combined_clear = 0x040, // I2C_CINT (read-only) 16.52 + Int_rx_uf_clear = 0x044, // I2C_CRXUF (read-only) 16.53 + Int_rx_of_clear = 0x048, // I2C_CRXOF (read-only) 16.54 + Int_tx_of_clear = 0x04c, // I2C_CTXOF (read-only) 16.55 + Int_rd_req_clear = 0x050, // I2C_CRXREQ (read-only) 16.56 + Int_tx_abort_clear = 0x054, // I2C_CTXABT (read-only) 16.57 + Int_rx_done_clear = 0x058, // I2C_CRXDN (read-only) 16.58 + Int_activity_clear = 0x05c, // I2C_CACT (read-only) 16.59 + Int_stop_clear = 0x060, // I2C_CSTP (read-only) 16.60 + Int_start_clear = 0x064, // I2C_CSTT (read-only) 16.61 + Int_call_clear = 0x068, // I2C_CGC (read-only) 16.62 + I2c_enable = 0x06c, // I2C_ENB 16.63 + I2c_status = 0x070, // I2C_ST (read-only) 16.64 + I2c_sda_hold_time = 0x07c, // I2C_SDAHD 16.65 + Trans_abort_status = 0x080, // I2C_ABTSRC (read-only) 16.66 + I2c_dma_ctrl = 0x088, // I2C_DMACR 16.67 + I2c_trans_data_lvl = 0x08c, // I2C_DMATDLR 16.68 + I2c_recv_data_lvl = 0x090, // I2C_DMARDLR 16.69 + I2c_sda_setup_time = 0x094, // I2C_SDASU 16.70 + I2c_ack_call = 0x098, // I2C_ACKGC 16.71 + I2c_enable_status = 0x09c, // I2C_ENBST (read-only) 16.72 + 16.73 + // X1600 only... 16.74 + 16.75 + High_high_count = 0x024, // I2C_HHCNT 16.76 + High_low_count = 0x028, // I2C_HLCNT 16.77 + Int_raw_status = 0x034, // I2C_RINTST (read-only) 16.78 + Tx_fifo_count = 0x074, // I2C_TXFLR (read-only) 16.79 + Rx_fifo_count = 0x078, // I2C_RXFLR (read-only) 16.80 + Slv_data_nack = 0x084, // I2CSDNACK 16.81 + I2c_spike_suppress = 0x0a0, // I2C_FSPKLEN 16.82 + 16.83 + // Register block spacing. 16.84 + 16.85 + I2c_block_offset = 0x1000 16.86 +}; 16.87 + 16.88 +enum I2c_control_bits : unsigned 16.89 +{ 16.90 + I2c_disable_slave = 0x40, // SLVDIS (slave disabled) 16.91 + I2c_enable_restart = 0x20, // RESTART 16.92 + I2c_master_10bit = 0x10, // MATP (read-only) 16.93 + I2c_slave_10bit = 0x08, // SATP 16.94 + I2c_speed_mode_mask = 0x06, // SPEED 16.95 + I2c_enable_master = 0x01, // MD (master enabled) 16.96 + I2c_speed_bit = 1, // SPD 16.97 +}; 16.98 + 16.99 +enum I2c_speed_mode_values : unsigned 16.100 +{ 16.101 + I2c_speed_standard = 1, 16.102 + I2c_speed_fast = 2, 16.103 + I2c_speed_high = 3, 16.104 +}; 16.105 + 16.106 +enum I2c_enable_bits : unsigned 16.107 +{ 16.108 + I2c_enable_enabled = 0x01, // I2CEN 16.109 +}; 16.110 + 16.111 +enum I2c_status_bits : unsigned 16.112 +{ 16.113 + I2c_status_master_act = 0x20, // MSTACT (master active) 16.114 + I2c_status_rx_nempty = 0x08, // RFNE (read queue not empty) 16.115 + I2c_status_tx_empty = 0x04, // TFE (write queue empty) 16.116 + I2c_status_tx_nfull = 0x02, // TFNF (write queue not full) 16.117 + I2c_status_active = 0x01, // ACT (device active as master or slave) 16.118 +}; 16.119 + 16.120 +enum I2c_target_bits : unsigned 16.121 +{ 16.122 + I2c_target_master_10bit = 0x1000, 16.123 + I2c_target_special = 0x0800, // SPECIAL: perform general call or start byte 16.124 + I2c_target_start_byte = 0x0400, // Special: start byte (1) or general call (0) 16.125 + I2c_target_10bits = 0x3ff, // Mask for 10-bit address 16.126 + I2c_target_7bits = 0x7f, // Mask for 7-bit address 16.127 +}; 16.128 + 16.129 +enum I2c_hold_control_bits : unsigned 16.130 +{ 16.131 + /* The hold enable flag has been removed since the JZ4780 and the hold time 16.132 + field widened. */ 16.133 + 16.134 + I2c_hold_mask = 0xffff, 16.135 +}; 16.136 + 16.137 +enum I2c_setup_control_bits : unsigned 16.138 +{ 16.139 + I2c_setup_mask = 0x0ff, // SDASU 16.140 +}; 16.141 + 16.142 +enum I2c_command_bits : unsigned 16.143 +{ 16.144 + I2c_command_restart = 0x400, // RESTART: explicit restart before next byte 16.145 + I2c_command_stop = 0x200, // STOP: explicit stop after next byte 16.146 + I2c_command_no_stop = 0x000, 16.147 + I2c_command_read = 0x100, // CMD 16.148 + I2c_command_write = 0x000, // CMD 16.149 +}; 16.150 + 16.151 +enum I2c_fifo_bits : unsigned 16.152 +{ 16.153 + I2c_fifo_limit = 64, // RXTL, TXTL (256 noted in field description) 16.154 +}; 16.155 + 16.156 +enum Int_bits : unsigned 16.157 +{ 16.158 + Int_call = 0x800, // IGC (general call received) 16.159 + Int_start = 0x400, // ISTT (start/restart condition occurred) 16.160 + Int_stop = 0x200, // ISTP (stop condition occurred) 16.161 + Int_activity = 0x100, // IACT (bus activity interrupt) 16.162 + Int_rx_done = 0x080, // RXDN (read from master device done) 16.163 + Int_tx_abort = 0x040, // TXABT (transmit abort) 16.164 + Int_rd_req = 0x020, // RDREQ (read request from master device) 16.165 + Int_tx_empty = 0x010, // TXEMP (threshold reached or passed) 16.166 + Int_tx_of = 0x008, // TXOF (overflow when writing to queue) 16.167 + Int_rx_full = 0x004, // RXFL (threshold reached or exceeded) 16.168 + Int_rx_of = 0x002, // RXOF (overflow from device) 16.169 + Int_rx_uf = 0x001, // RXUF (underflow when reading from queue) 16.170 +}; 16.171 + 16.172 + 16.173 + 16.174 +// Initialise a channel. 16.175 + 16.176 +I2c_channel::I2c_channel(l4_addr_t start, 16.177 + enum Clock_identifiers clock, 16.178 + Cpm_chip *cpm, 16.179 + uint32_t frequency) 16.180 +: _cpm(cpm), _frequency(frequency) 16.181 +{ 16.182 + _regs = new Hw::Mmio_register_block<32>(start); 16.183 + _cpm->start_clock(clock); 16.184 +} 16.185 + 16.186 +// Enable the channel. 16.187 + 16.188 +void 16.189 +I2c_channel::enable() 16.190 +{ 16.191 + _regs[I2c_enable] = I2c_enable_enabled; 16.192 + while (!(_regs[I2c_enable_status] & I2c_enable_enabled)); 16.193 +} 16.194 + 16.195 +// Disable the channel. 16.196 + 16.197 +void 16.198 +I2c_channel::disable() 16.199 +{ 16.200 + _regs[I2c_enable] = 0; 16.201 + while (_regs[I2c_enable_status] & I2c_enable_enabled); 16.202 +} 16.203 + 16.204 +// Return the configured frequency. 16.205 + 16.206 +uint32_t 16.207 +I2c_channel::get_frequency() 16.208 +{ 16.209 + return _frequency; 16.210 +} 16.211 + 16.212 +// Set the frequency-related peripheral parameters. 16.213 + 16.214 +void 16.215 +I2c_channel::set_frequency() 16.216 +{ 16.217 + // The APB clock (PCLK) is used to drive I2C transfers. Its value must be 16.218 + // obtained from the CPM unit. It is known as I2C_DEV_CLK here and is scaled 16.219 + // to kHz in order to keep the numbers easily representable, as is the bus 16.220 + // frequency. 16.221 + 16.222 + uint32_t i2c_dev_clk = _cpm->get_frequency(Clock_pclock) / 1000; 16.223 + 16.224 + // Note that this is not I2C_DEV_CLK but the actual I2C bus frequency. 16.225 + 16.226 + uint32_t i2c_clk = _frequency / 1000; 16.227 + 16.228 + // Select the appropriate speed. 16.229 + 16.230 + unsigned int speed = (i2c_clk <= 100) ? I2c_speed_standard 16.231 + : (i2c_clk <= 400 ? I2c_speed_fast 16.232 + : I2c_speed_high); 16.233 + 16.234 + // NOTE: Permit broader configuration elsewhere. 16.235 + 16.236 + _regs[I2c_control] = (speed << I2c_speed_bit) | 16.237 + I2c_disable_slave | 16.238 + I2c_enable_restart | 16.239 + I2c_enable_master; 16.240 + 16.241 + // According to the programming manual, if the PCLK period is T{I2C_DEV_CLK} 16.242 + // then the I2C clock period is... 16.243 + 16.244 + // T{SCL} = T{SCL_high} + T{SCL_low} 16.245 + 16.246 + // Where... 16.247 + 16.248 + // T{SCL_low} = T{I2C_DEV_CLK} * (#cycles for low signal) 16.249 + // T{SCL_high} = T{I2C_DEV_CLK} * (#cycles for high signal) 16.250 + 16.251 + // Since, with minimum periods being defined... 16.252 + 16.253 + // T{SCL} >= T{min_SCL} 16.254 + // T{SCL_low} >= T{min_SCL_low} 16.255 + // T{SCL_high} >= T{min_SCL_high} 16.256 + // T{min_SCL} = T{min_SCL_low} + T{min_SCL_high} 16.257 + 16.258 + // Then the following applies... 16.259 + 16.260 + // T{I2C_DEV_CLK} * (#cycles for low signal)) >= T{min_SCL_low} 16.261 + // T{I2C_DEV_CLK} * (#cycles for high signal) >= T{min_SCL_high} 16.262 + 16.263 + // To work with different clock speeds while maintaining the low-to-high 16.264 + // ratios: 16.265 + 16.266 + // T{min_SCL_low} = T{min_SCL} * T{min_SCL_low} / T{min_SCL} 16.267 + // = T{min_SCL} * (T{min_SCL_low} / (T{min_SCL_low} + T{min_SCL_high})) 16.268 + 16.269 + // T{min_SCL_high} = T{min_SCL} * T{min_SCL_high} / T{min_SCL} 16.270 + // = T{min_SCL} * (T{min_SCL_high} / (T{min_SCL_low} + T{min_SCL_high})) 16.271 + 16.272 + // Constraints are given with respect to the high and low count registers. 16.273 + 16.274 + // #cycles for high signal = I2CxHCNT + 8 16.275 + // #cycles for low signal = I2CxLCNT + 1 16.276 + 16.277 + // From earlier, this yields... 16.278 + 16.279 + // T{I2C_DEV_CLK} * (I2CxLCNT + 1) >= T{min_SCL_low} 16.280 + // T{I2C_DEV_CLK} * (I2CxHCNT + 8) >= T{min_SCL_high} 16.281 + 16.282 + // Rearranging... 16.283 + 16.284 + // I2CxLCNT >= (T{min_SCL_low} / T{I2C_DEV_CLK}) - 1 16.285 + // >= T{min_SCL_low} * I2C_DEV_CLK - 1 16.286 + 16.287 + // I2CxHCNT >= (T{min_SCL_high} / T{I2C_DEV_CLK}) - 8 16.288 + // >= T{min_SCL_high} * I2C_DEV_CLK - 8 16.289 + 16.290 + // Introducing the definitions for the high and low periods... 16.291 + 16.292 + // I2CxLCNT >= T{min_SCL} * (T{min_SCL_low} / (T{min_SCL_low} + T{min_SCL_high})) * I2C_DEV_CLK - 1 16.293 + // >= (T{min_SCL_low} / T{min_SCL}) * I2C_DEV_CLK / I2C_BUS_CLK - 1 16.294 + 16.295 + // I2CxHCNT >= T{min_SCL} * (T{min_SCL_high} / (T{min_SCL_low} + T{min_SCL_high})) * I2C_DEV_CLK - 8 16.296 + // >= (T{min_SCL_high} / T{min_SCL}) * I2C_DEV_CLK / I2C_BUS_CLK - 8 16.297 + 16.298 + uint32_t high_reg, low_reg; 16.299 + uint32_t high_count, low_count; 16.300 + int32_t hold_count; 16.301 + uint32_t setup_count; 16.302 + 16.303 + // Level hold times: 16.304 + 16.305 + // Standard Fast High 16.306 + // SCL low 4.7us 1.3us 0.5us 16.307 + // SCL high 4.0us 0.6us 0.26us + 16.308 + // SCL period 8.7us 1.9us 0.76us = 16.309 + 16.310 + // See: UM10204 "I2C-bus specification and user manual" 16.311 + // Table 10: t{LOW} and t{HIGH} 16.312 + 16.313 + if (i2c_clk <= 100) // 100 kHz 16.314 + { 16.315 + low_count = (i2c_dev_clk * 47) / (i2c_clk * 87) - 1; 16.316 + high_count = (i2c_dev_clk * 40) / (i2c_clk * 87) - 8; 16.317 + low_reg = Std_low_count; 16.318 + high_reg = Std_high_count; 16.319 + } 16.320 + else if (i2c_clk <= 400) // 400 kHz 16.321 + { 16.322 + low_count = (i2c_dev_clk * 13) / (i2c_clk * 19) - 1; 16.323 + high_count = (i2c_dev_clk * 6) / (i2c_clk * 19) - 8; 16.324 + low_reg = Fast_low_count; 16.325 + high_reg = Fast_high_count; 16.326 + } 16.327 + else // > 400 kHz 16.328 + { 16.329 + // Note how the frequencies are scaled to accommodate the extra precision 16.330 + // required. 16.331 + 16.332 + low_count = (i2c_dev_clk / 10 * 50) / (i2c_clk / 10 * 76) - 1; 16.333 + high_count = (i2c_dev_clk / 10 * 26) / (i2c_clk / 10 * 76) - 8; 16.334 + low_reg = High_low_count; 16.335 + high_reg = High_high_count; 16.336 + } 16.337 + 16.338 + // Minimum counts are 8 and 6 for low and high respectively. 16.339 + 16.340 + _regs[low_reg] = low_count < 8 ? 8 : low_count; 16.341 + _regs[high_reg] = high_count < 6 ? 6 : high_count; 16.342 + 16.343 + // Data hold and setup times: 16.344 + 16.345 + // Standard Fast High 16.346 + // t{HD;DAT} 300ns 300ns 300ns 16.347 + // t{SU;DAT} 250ns 100ns 50ns 16.348 + 16.349 + // See: UM10204 "I2C-bus specification and user manual" 16.350 + // Table 10: t{HD;DAT} and t{SU;DAT}, also note [3] 16.351 + 16.352 + // T{delay} = (I2CSDAHD + 2) * T{I2C_DEV_CLK} 16.353 + // I2CSDAHD = T{delay} / T{I2C_DEV_CLK} - 2 16.354 + // I2CSDAHD = I2C_DEV_CLK * T{delay} - 2 16.355 + 16.356 + // Since the device clock is in kHz (scaled down by 1000) and the times are 16.357 + // given in ns (scaled up by 1000000000), a division of 1000000 is introduced. 16.358 + 16.359 + hold_count = (i2c_dev_clk * 300) / 1000000 - 1; 16.360 + 16.361 + _regs[I2c_sda_hold_time] = (_regs[I2c_sda_hold_time] & ~I2c_hold_mask) | 16.362 + (hold_count < 0 ? 0 16.363 + : (hold_count < (int) I2c_hold_mask ? (uint32_t) hold_count 16.364 + : I2c_hold_mask)); 16.365 + 16.366 + // I2C_SDASU is apparently not used in master mode. 16.367 + 16.368 + // T{delay} = (I2CSDASU - 1) * T{I2C_DEV_CLK} 16.369 + // I2CSDASU = T{delay} / T{I2C_DEV_CLK} + 1 16.370 + // I2CSDASU = I2C_DEV_CLK * T{delay} + 1 16.371 + 16.372 + if (i2c_clk <= 100) 16.373 + setup_count = (i2c_dev_clk * 250) / 1000000 + 1; 16.374 + else if (i2c_clk <= 400) 16.375 + setup_count = (i2c_dev_clk * 100) / 1000000 + 1; 16.376 + else 16.377 + setup_count = (i2c_dev_clk * 50) / 1000000 + 1; 16.378 + 16.379 + _regs[I2c_sda_setup_time] = (_regs[I2c_sda_setup_time] & ~I2c_setup_mask) | 16.380 + (setup_count < I2c_setup_mask ? setup_count : I2c_setup_mask); 16.381 +} 16.382 + 16.383 +// Set the target address and enable transfer. 16.384 +// NOTE: Only supporting 7-bit addresses currently. 16.385 + 16.386 +void 16.387 +I2c_channel::set_target(uint8_t address) 16.388 +{ 16.389 + disable(); 16.390 + set_frequency(); 16.391 + _regs[I2c_target_address] = address & I2c_target_7bits; 16.392 + init_parameters(); 16.393 + enable(); 16.394 +} 16.395 + 16.396 + 16.397 + 16.398 +// Reset interrupt flags upon certain conditions. 16.399 + 16.400 +void 16.401 +I2c_channel::reset_flags() 16.402 +{ 16.403 + volatile uint32_t r; 16.404 + 16.405 + _regs[Int_mask] = 0; 16.406 + 16.407 + // Read from the register to clear interrupts. 16.408 + 16.409 + r = _regs[Int_combined_clear]; 16.410 + (void) r; 16.411 +} 16.412 + 16.413 +// Initialise interrupt flags and queue thresholds for reading and writing. 16.414 + 16.415 +void 16.416 +I2c_channel::init_parameters() 16.417 +{ 16.418 + // Handle read queue conditions for data, write queue conditions for commands. 16.419 + 16.420 + reset_flags(); 16.421 + 16.422 + _regs[Tx_fifo_thold] = 0; // write when 0 in queue 16.423 +} 16.424 + 16.425 + 16.426 + 16.427 +// Return whether the device is active. 16.428 + 16.429 +int 16.430 +I2c_channel::active() 16.431 +{ 16.432 + return _regs[I2c_status] & I2c_status_master_act; 16.433 +} 16.434 + 16.435 +// Return whether data is available to receive. 16.436 + 16.437 +int 16.438 +I2c_channel::have_input() 16.439 +{ 16.440 + return _regs[I2c_status] & I2c_status_rx_nempty; 16.441 +} 16.442 + 16.443 +// Return whether data is queued for sending. 16.444 + 16.445 +int 16.446 +I2c_channel::have_output() 16.447 +{ 16.448 + return !(_regs[I2c_status] & I2c_status_tx_empty); 16.449 +} 16.450 + 16.451 +// Return whether data can be queued for sending. 16.452 + 16.453 +int 16.454 +I2c_channel::can_send() 16.455 +{ 16.456 + return _regs[I2c_status] & I2c_status_tx_nfull; 16.457 +} 16.458 + 16.459 +// Return whether a receive operation has failed. 16.460 + 16.461 +int 16.462 +I2c_channel::read_failed() 16.463 +{ 16.464 + return _regs[Int_status] & Int_rx_of; 16.465 +} 16.466 + 16.467 +// Return whether a send operation has failed. 16.468 + 16.469 +int 16.470 +I2c_channel::write_failed() 16.471 +{ 16.472 + return _regs[Int_status] & Int_tx_abort; 16.473 +} 16.474 + 16.475 +int 16.476 +I2c_channel::read_done() 16.477 +{ 16.478 + return _pos == _total; 16.479 +} 16.480 + 16.481 +int 16.482 +I2c_channel::write_done() 16.483 +{ 16.484 + return (_reqpos == _total) && !have_output(); 16.485 +} 16.486 + 16.487 +unsigned 16.488 +I2c_channel::have_read() 16.489 +{ 16.490 + return _pos; 16.491 +} 16.492 + 16.493 +unsigned 16.494 +I2c_channel::have_written() 16.495 +{ 16.496 + return _reqpos; 16.497 +} 16.498 + 16.499 +int 16.500 +I2c_channel::failed() 16.501 +{ 16.502 + return _fail; 16.503 +} 16.504 + 16.505 + 16.506 + 16.507 +// Send read commands for empty queue entries. 16.508 + 16.509 +void 16.510 +I2c_channel::queue_reads() 16.511 +{ 16.512 + unsigned int remaining = _total - _reqpos; 16.513 + unsigned int queued = _reqpos - _pos; 16.514 + unsigned int can_queue = I2c_fifo_limit - queued; 16.515 + 16.516 + // Keep the number of reads in progress below the length of the read queue. 16.517 + 16.518 + if (!can_queue) 16.519 + return; 16.520 + 16.521 + // At most, only queue as many reads as are remaining. 16.522 + 16.523 + if (remaining < can_queue) 16.524 + can_queue = remaining; 16.525 + 16.526 + // Queue read requests for any remaining queue entries. 16.527 + 16.528 + while (can_queue && can_send()) 16.529 + { 16.530 + uint32_t stop = _stop && (_reqpos == _total - 1) ? I2c_command_stop : I2c_command_no_stop; 16.531 + 16.532 + _regs[I2c_data_command] = I2c_command_read | stop; 16.533 + _reqpos++; 16.534 + can_queue--; 16.535 + } 16.536 + 16.537 + // Update the threshold to be notified of any reduced remaining amount. 16.538 + 16.539 + set_read_threshold(); 16.540 +} 16.541 + 16.542 +// Send write commands for empty queue entries. 16.543 + 16.544 +void 16.545 +I2c_channel::queue_writes() 16.546 +{ 16.547 + unsigned int remaining = _total - _reqpos; 16.548 + unsigned int can_queue = I2c_fifo_limit; 16.549 + 16.550 + if (remaining < can_queue) 16.551 + can_queue = remaining; 16.552 + 16.553 + // Queue write requests for any remaining queue entries. 16.554 + 16.555 + while (can_queue && can_send()) 16.556 + { 16.557 + uint32_t stop = _stop && (_reqpos == _total - 1) ? I2c_command_stop : I2c_command_no_stop; 16.558 + 16.559 + _regs[I2c_data_command] = I2c_command_write | _buf[_reqpos] | stop; 16.560 + _reqpos++; 16.561 + can_queue--; 16.562 + } 16.563 +} 16.564 + 16.565 +// Store read command results from the queue. 16.566 + 16.567 +void 16.568 +I2c_channel::store_reads() 16.569 +{ 16.570 + // Read any input and store it in the buffer. 16.571 + 16.572 + while (have_input() && (_pos < _reqpos)) 16.573 + { 16.574 + _buf[_pos] = _regs[I2c_data_command] & 0xff; 16.575 + _pos++; 16.576 + } 16.577 +} 16.578 + 16.579 +void 16.580 +I2c_channel::set_read_threshold() 16.581 +{ 16.582 + unsigned int queued = _reqpos - _pos; 16.583 + 16.584 + if (!queued) 16.585 + return; 16.586 + 16.587 + // Read all expected. 16.588 + 16.589 + _regs[Rx_fifo_thold] = queued - 1; 16.590 +} 16.591 + 16.592 +// Read from the target device. 16.593 + 16.594 +void 16.595 +I2c_channel::start_read(uint8_t buf[], unsigned int total, int stop) 16.596 +{ 16.597 + _buf = buf; 16.598 + _total = total; 16.599 + _pos = 0; 16.600 + _reqpos = 0; 16.601 + _fail = 0; 16.602 + _stop = stop; 16.603 + 16.604 + reset_flags(); 16.605 + 16.606 + _regs[Int_mask] = Int_rx_full | // read condition (reading needed) 16.607 + Int_rx_of | // abort condition 16.608 + Int_tx_abort; // general abort condition 16.609 + 16.610 + // Perform initial read requests. 16.611 + 16.612 + read(); 16.613 +} 16.614 + 16.615 +void 16.616 +I2c_channel::read() 16.617 +{ 16.618 + // Test for the general transfer abort condition. 16.619 + 16.620 + if (read_failed() || write_failed()) 16.621 + { 16.622 + _fail = 1; 16.623 + _regs[Int_mask] = 0; 16.624 + disable(); 16.625 + enable(); 16.626 + return; 16.627 + } 16.628 + 16.629 + if (_regs[Int_status] & Int_rx_full) 16.630 + store_reads(); 16.631 + 16.632 + // Always attempt to queue more read requests. 16.633 + 16.634 + queue_reads(); 16.635 +} 16.636 + 16.637 +// Write to the target device. 16.638 + 16.639 +void 16.640 +I2c_channel::start_write(uint8_t buf[], unsigned int total, int stop) 16.641 +{ 16.642 + _buf = buf; 16.643 + _total = total; 16.644 + _reqpos = 0; 16.645 + _fail = 0; 16.646 + _stop = stop; 16.647 + 16.648 + reset_flags(); 16.649 + 16.650 + // Enable interrupts for further writes. 16.651 + 16.652 + _regs[Int_mask] = Int_tx_empty | // write condition (writing needed) 16.653 + Int_tx_abort; // abort condition 16.654 + 16.655 + // Perform initial writes. 16.656 + 16.657 + write(); 16.658 +} 16.659 + 16.660 +void 16.661 +I2c_channel::write() 16.662 +{ 16.663 + if (write_failed()) 16.664 + { 16.665 + _fail = 1; 16.666 + _regs[Int_mask] = 0; 16.667 + disable(); 16.668 + enable(); 16.669 + return; 16.670 + } 16.671 + 16.672 + if (_regs[Int_status] & Int_tx_empty) 16.673 + queue_writes(); 16.674 +} 16.675 + 16.676 +// Explicitly stop communication. 16.677 + 16.678 +void 16.679 +I2c_channel::stop() 16.680 +{ 16.681 +} 16.682 + 16.683 + 16.684 + 16.685 +// Initialise the I2C controller. 16.686 + 16.687 +I2c_chip::I2c_chip(l4_addr_t start, l4_addr_t end, 16.688 + Cpm_chip *cpm, 16.689 + uint32_t frequency) 16.690 +: _start(start), _end(end), _cpm(cpm), _frequency(frequency) 16.691 +{ 16.692 +} 16.693 + 16.694 +// Obtain a channel object. 16.695 + 16.696 +I2c_channel * 16.697 +I2c_chip::get_channel(uint8_t channel) 16.698 +{ 16.699 + l4_addr_t block = _start + channel * I2c_block_offset; 16.700 + 16.701 + // NOTE: Defining all the possible clocks. 16.702 + 16.703 + enum Clock_identifiers clocks[] = {Clock_i2c0, Clock_i2c1, Clock_i2c2, Clock_i2c3, Clock_i2c4}; 16.704 + 16.705 + if (channel < num_channels()) 16.706 + return new I2c_channel(block, clocks[channel], _cpm, _frequency); 16.707 + else 16.708 + throw -L4_EINVAL; 16.709 +}
17.1 --- a/pkg/devices/lib/i2c/src/jz4780.cc Sat Oct 28 01:15:45 2023 +0200 17.2 +++ b/pkg/devices/lib/i2c/src/jz4780.cc Sun Oct 29 16:14:38 2023 +0100 17.3 @@ -1,7 +1,7 @@ 17.4 /* 17.5 * I2C support for the JZ4780. 17.6 * 17.7 - * Copyright (C) 2017, 2018, 2021 Paul Boddie <paul@boddie.org.uk> 17.8 + * Copyright (C) 2017, 2018, 2021, 2023 Paul Boddie <paul@boddie.org.uk> 17.9 * 17.10 * This program is free software; you can redistribute it and/or 17.11 * modify it under the terms of the GNU General Public License as 17.12 @@ -20,13 +20,6 @@ 17.13 */ 17.14 17.15 #include <l4/devices/i2c-jz4780.h> 17.16 -#include <l4/devices/hw_mmio_register_block.h> 17.17 - 17.18 -#include <l4/sys/icu.h> 17.19 -#include <l4/util/util.h> 17.20 -#include <sys/time.h> 17.21 - 17.22 -#include <cstdio> 17.23 17.24 /* 17.25 I2C pins: 17.26 @@ -42,573 +35,16 @@ 17.27 See: http://mipscreator.imgtec.com/CI20/hardware/board/ci20_jz4780_v2.0.pdf 17.28 */ 17.29 17.30 -enum Regs 17.31 -{ 17.32 - Smb_control = 0x000, // SMBCON 17.33 - Smb_target_address = 0x004, // SMBTAR 17.34 - Smb_slave_address = 0x008, // SMBSAR 17.35 - Smb_data_command = 0x010, // SMBDC 17.36 - Std_high_count = 0x014, // SMBSHCNT 17.37 - Std_low_count = 0x018, // SMBSLCNT 17.38 - Fast_high_count = 0x01c, // SMBFHCNT 17.39 - Fast_low_count = 0x020, // SMBFLCNT 17.40 - Int_status = 0x02c, // SMBINTST (read-only) 17.41 - Int_mask = 0x030, // SMBINTM 17.42 - 17.43 - Rx_fifo_thold = 0x038, // SMBRXTL 17.44 - Tx_fifo_thold = 0x03c, // SMBTXTL 17.45 - Int_combined_clear = 0x040, // SMBCINT (read-only) 17.46 - Int_rx_uf_clear = 0x044, // SMBCRXUF (read-only) 17.47 - Int_rx_of_clear = 0x048, // SMBCRXOF (read-only) 17.48 - Int_tx_of_clear = 0x04c, // SMBCTXOF (read-only) 17.49 - Int_rd_req_clear = 0x050, // SMBCRXREQ (read-only) 17.50 - Int_tx_abort_clear = 0x054, // SMBCTXABT (read-only) 17.51 - Int_rx_done_clear = 0x058, // SMBCRXDN (read-only) 17.52 - Int_activity_clear = 0x05c, // SMBCACT (read-only) 17.53 - Int_stop_clear = 0x060, // SMBCSTP (read-only) 17.54 - Int_start_clear = 0x064, // SMBCSTT (read-only) 17.55 - Int_call_clear = 0x068, // SMBCGC (read-only) 17.56 - Smb_enable = 0x06c, // SMBENB 17.57 - Smb_status = 0x070, // SMBST (read-only) 17.58 - 17.59 - Tx_fifo_count = 0x074, // SMBTXFLR (read-only) 17.60 - Rx_fifo_count = 0x078, // SMBRXFLR (read-only) 17.61 - 17.62 - Trans_abort_status0 = 0x080, // SMBABTSRC (read-only) 17.63 - Trans_abort_status1 = 0x084, // ... (read-only) 17.64 - 17.65 - Smb_dma_ctrl = 0x088, // SMBDMACR 17.66 - Smb_trans_data_lvl = 0x08c, // SMBDMATDLR 17.67 - Smb_recv_data_lvl = 0x090, // SMBDMARDLR 17.68 - Smb_sda_setup_time = 0x094, // SMBSDASU 17.69 - Smb_ack_call = 0x098, // SMBACKGC 17.70 - 17.71 - Smb_enable_status = 0x09c, // SMBENBST (read-only) 17.72 - Smb_sda_hold_time = 0x0d0, // SMBSDAHD 17.73 - 17.74 - Smb_block_offset = 0x1000 17.75 -}; 17.76 - 17.77 -enum Smb_control_bits : unsigned 17.78 -{ 17.79 - Smb_no_stop_empty = 0x80, // STPHLD (no STP condition when queue empty) 17.80 - Smb_disable_slave = 0x40, // SLVDIS (slave disabled) 17.81 - Smb_enable_restart = 0x20, // REST 17.82 - Smb_enable_master = 0x01, // MD (master enabled) 17.83 - Smb_speed_bit = 1, // SPD 17.84 -}; 17.85 - 17.86 -enum Smb_enable_bits : unsigned 17.87 -{ 17.88 - Smb_enable_enabled = 0x01, // SMBEN 17.89 -}; 17.90 - 17.91 -enum Smb_status_bits : unsigned 17.92 -{ 17.93 - Smb_status_master_act = 0x20, // MSTACT (master active) 17.94 - Smb_status_rx_nempty = 0x08, // RFNE (read queue not empty) 17.95 - Smb_status_tx_empty = 0x04, // TFE (write queue empty) 17.96 - Smb_status_tx_nfull = 0x02, // TFNF (write queue not full) 17.97 - Smb_status_active = 0x01, // ACT (device active as master or slave) 17.98 -}; 17.99 - 17.100 -enum Smb_target_bits : unsigned 17.101 -{ 17.102 - Smb_target_7bits = 0x7f, 17.103 -}; 17.104 - 17.105 -enum Smb_hold_control_bits : unsigned 17.106 -{ 17.107 - Smb_hold_enable = 0x100, // HDENB 17.108 - Smb_hold_disable = 0x000, // HDENB 17.109 - Smb_hold_mask = 0x1ff, 17.110 -}; 17.111 - 17.112 -enum Smb_setup_control_bits : unsigned 17.113 -{ 17.114 - Smb_setup_mask = 0x0ff, 17.115 -}; 17.116 - 17.117 -enum Smb_command_bits : unsigned 17.118 -{ 17.119 - Smb_command_read = 0x100, // CMD 17.120 - Smb_command_write = 0x000, // CMD 17.121 -}; 17.122 - 17.123 -enum Smb_fifo_bits : unsigned 17.124 -{ 17.125 - Smb_fifo_limit = 16, 17.126 -}; 17.127 - 17.128 -enum Int_bits : unsigned 17.129 -{ 17.130 - Int_call = 0x800, // IGC (general call received) 17.131 - Int_start = 0x400, // ISTT (start/restart condition occurred) 17.132 - Int_stop = 0x200, // ISTP (stop condition occurred) 17.133 - Int_activity = 0x100, // IACT (bus activity interrupt) 17.134 - Int_rx_done = 0x080, // RXDN (read from master device done) 17.135 - Int_tx_abort = 0x040, // TXABT (transmit abort) 17.136 - Int_rd_req = 0x020, // RDREQ (read request from master device) 17.137 - Int_tx_empty = 0x010, // TXEMP (threshold reached or passed) 17.138 - Int_tx_of = 0x008, // TXOF (overflow when writing to queue) 17.139 - Int_rx_full = 0x004, // RXFL (threshold reached or exceeded) 17.140 - Int_rx_of = 0x002, // RXOF (overflow from device) 17.141 - Int_rx_uf = 0x001, // RXUF (underflow when reading from queue) 17.142 -}; 17.143 - 17.144 17.145 17.146 // Initialise a channel. 17.147 17.148 I2c_jz4780_channel::I2c_jz4780_channel(l4_addr_t start, 17.149 - Cpm_jz4780_chip *cpm, 17.150 + enum Clock_identifiers clock, 17.151 + Cpm_chip *cpm, 17.152 uint32_t frequency) 17.153 -: _cpm(cpm), _frequency(frequency) 17.154 -{ 17.155 - _regs = new Hw::Mmio_register_block<32>(start); 17.156 -} 17.157 - 17.158 -// Enable the channel. 17.159 - 17.160 -void 17.161 -I2c_jz4780_channel::enable() 17.162 -{ 17.163 - _regs[Smb_enable] = Smb_enable_enabled; 17.164 - while (!(_regs[Smb_enable_status] & Smb_enable_enabled)); 17.165 -} 17.166 - 17.167 -// Disable the channel. 17.168 - 17.169 -void 17.170 -I2c_jz4780_channel::disable() 17.171 -{ 17.172 - _regs[Smb_enable] = 0; 17.173 - while (_regs[Smb_enable_status] & Smb_enable_enabled); 17.174 -} 17.175 - 17.176 -// Set the frequency-related peripheral parameters. 17.177 - 17.178 -void 17.179 -I2c_jz4780_channel::set_frequency() 17.180 -{ 17.181 - // The APB clock (PCLK) is used to drive I2C transfers. Its value must be 17.182 - // obtained from the CPM unit. It is known as SMB_CLK here and is scaled to 17.183 - // kHz in order to keep the numbers easily representable, as is the bus 17.184 - // frequency. 17.185 - 17.186 - uint32_t smb_clk = _cpm->get_frequency(Clock_pclock) / 1000; 17.187 - uint32_t i2c_clk = _frequency / 1000; 17.188 - unsigned int speed = (i2c_clk <= 100) ? 1 : 2; 17.189 - 17.190 - _regs[Smb_control] = _regs[Smb_control] | (speed << Smb_speed_bit) | 17.191 - Smb_disable_slave | 17.192 - Smb_enable_restart | 17.193 - Smb_enable_master; 17.194 - 17.195 - // According to the programming manual, if the PCLK period is T{SMB_CLK} 17.196 - // then the I2C clock period is... 17.197 - 17.198 - // T{SCL} = T{SCL_high} + T{SCL_low} 17.199 - 17.200 - // Where... 17.201 - 17.202 - // T{SCL_low} = T{SMB_CLK} * (#cycles for low signal) 17.203 - // T{SCL_high} = T{SMB_CLK} * (#cycles for high signal) 17.204 - 17.205 - // Since, with minimum periods being defined... 17.206 - 17.207 - // T{SCL} >= T{min_SCL} 17.208 - // T{SCL_low} >= T{min_SCL_low} 17.209 - // T{SCL_high} >= T{min_SCL_high} 17.210 - // T{min_SCL} = T{min_SCL_low} + T{min_SCL_high} 17.211 - 17.212 - // Then the following applies... 17.213 - 17.214 - // T{SMB_CLK} * (#cycles for low signal)) >= T{min_SCL_low} 17.215 - // T{SMB_CLK} * (#cycles for high signal) >= T{min_SCL_high} 17.216 - 17.217 - // To work with different clock speeds while maintaining the low-to-high 17.218 - // ratios: 17.219 - 17.220 - // T{min_SCL_low} = T{min_SCL} * T{min_SCL_low} / T{min_SCL} 17.221 - // = T{min_SCL} * (T{min_SCL_low} / (T{min_SCL_low} + T{min_SCL_high})) 17.222 - 17.223 - // T{min_SCL_high} = T{min_SCL} * T{min_SCL_high} / T{min_SCL} 17.224 - // = T{min_SCL} * (T{min_SCL_high} / (T{min_SCL_low} + T{min_SCL_high})) 17.225 - 17.226 - // Constraints are given with respect to the high and low count registers. 17.227 - 17.228 - // #cycles for high signal = SMBxHCNT + 8 17.229 - // #cycles for low signal = SMBxLCNT + 1 17.230 - 17.231 - // From earlier, this yields... 17.232 - 17.233 - // T{SMB_CLK} * (SMBxLCNT + 1) >= T{min_SCL_low} 17.234 - // T{SMB_CLK} * (SMBxHCNT + 8) >= T{min_SCL_high} 17.235 - 17.236 - // Rearranging... 17.237 - 17.238 - // SMBxLCNT >= (T{min_SCL_low} / T{SMB_CLK}) - 1 17.239 - // >= T{min_SCL_low} * SMB_CLK - 1 17.240 - 17.241 - // SMBxHCNT >= (T{min_SCL_high} / T{SMB_CLK}) - 8 17.242 - // >= T{min_SCL_high} * SMB_CLK - 8 17.243 - 17.244 - // Introducing the definitions for the high and low periods... 17.245 - 17.246 - // SMBxLCNT >= T{min_SCL} * (T{min_SCL_low} / (T{min_SCL_low} + T{min_SCL_high})) * SMB_CLK - 1 17.247 - // >= (T{min_SCL_low} / T{min_SCL}) * SMB_CLK / I2C_CLK - 1 17.248 - 17.249 - // SMBxHCNT >= T{min_SCL} * (T{min_SCL_high} / (T{min_SCL_low} + T{min_SCL_high})) * SMB_CLK - 8 17.250 - // >= (T{min_SCL_high} / T{min_SCL}) * SMB_CLK / I2C_CLK - 8 17.251 - 17.252 - uint32_t high_reg, low_reg; 17.253 - uint32_t high_count, low_count; 17.254 - int32_t hold_count; 17.255 - uint32_t setup_count; 17.256 - 17.257 - // Level hold times: 17.258 - 17.259 - // Standard Fast 17.260 - // SCL low 4.7us 1.3us 17.261 - // SCL high 4.0us 0.6us + 17.262 - // SCL period 8.7us 1.9us = 17.263 - 17.264 - if (i2c_clk <= 100) // 100 kHz 17.265 - { 17.266 - low_count = (smb_clk * 47) / (i2c_clk * 87) - 1; 17.267 - high_count = (smb_clk * 40) / (i2c_clk * 87) - 8; 17.268 - low_reg = Std_low_count; 17.269 - high_reg = Std_high_count; 17.270 - } 17.271 - else 17.272 - { 17.273 - low_count = (smb_clk * 13) / (i2c_clk * 19) - 1; 17.274 - high_count = (smb_clk * 6) / (i2c_clk * 19) - 8; 17.275 - low_reg = Fast_low_count; 17.276 - high_reg = Fast_high_count; 17.277 - } 17.278 - 17.279 - // Minimum counts are 8 and 6 for low and high respectively. 17.280 - 17.281 - _regs[low_reg] = low_count < 8 ? 8 : low_count; 17.282 - _regs[high_reg] = high_count < 6 ? 6 : high_count; 17.283 - 17.284 - // Data hold and setup times: 17.285 - 17.286 - // Standard Fast 17.287 - // t{HD;DAT} 300ns 300ns 17.288 - // t{SU;DAT} 250ns 100ns 17.289 - 17.290 - // T{delay} = (SMBSDAHD + 1) * T{SMB_CLK} 17.291 - // SMBSDAHD = T{delay} / T{SMB_CLK} - 1 17.292 - // SMBSDAHD = SMB_CLK * T{delay} - 1 17.293 - 17.294 - hold_count = (smb_clk * 300) / 1000000 - 1; 17.295 - 17.296 - _regs[Smb_sda_hold_time] = (_regs[Smb_sda_hold_time] & ~Smb_hold_mask) | 17.297 - (hold_count >= 0 ? Smb_hold_enable : Smb_hold_disable) | 17.298 - (hold_count < 0 ? 0 : hold_count < 255 ? hold_count : 255); 17.299 - 17.300 - // T{delay} = (SMBSDASU - 1) * T{SMB_CLK} 17.301 - // SMBSDASU = T{delay} / T{SMB_CLK} + 1 17.302 - // SMBSDASU = SMB_CLK * T{delay} + 1 17.303 - 17.304 - if (i2c_clk <= 100) 17.305 - setup_count = (smb_clk * 250) / 1000000 + 1; 17.306 - else 17.307 - setup_count = (smb_clk * 100) / 1000000 + 1; 17.308 - 17.309 - _regs[Smb_sda_setup_time] = (_regs[Smb_sda_setup_time] & ~Smb_setup_mask) | 17.310 - (setup_count < 255 ? setup_count : 255); 17.311 -} 17.312 - 17.313 -// Set the target address and enable transfer. 17.314 -// NOTE: Only supporting 7-bit addresses currently. 17.315 - 17.316 -void 17.317 -I2c_jz4780_channel::set_target(uint8_t address) 17.318 -{ 17.319 - disable(); 17.320 - set_frequency(); 17.321 - _regs[Smb_target_address] = address & Smb_target_7bits; 17.322 - enable(); 17.323 - init_parameters(); 17.324 -} 17.325 - 17.326 - 17.327 - 17.328 -// Reset interrupt flags upon certain conditions. 17.329 - 17.330 -void 17.331 -I2c_jz4780_channel::reset_flags() 17.332 -{ 17.333 - volatile uint32_t r; 17.334 - 17.335 - _regs[Int_mask] = 0; 17.336 - 17.337 - // Read from the register to clear interrupts. 17.338 - 17.339 - r = _regs[Int_combined_clear]; 17.340 - (void) r; 17.341 -} 17.342 - 17.343 -// Initialise interrupt flags and queue thresholds for reading and writing. 17.344 - 17.345 -void 17.346 -I2c_jz4780_channel::init_parameters() 17.347 -{ 17.348 - // Handle read queue conditions for data, write queue conditions for commands. 17.349 - 17.350 - reset_flags(); 17.351 - 17.352 - _regs[Int_mask] = Int_rx_full | // read condition (reading needed) 17.353 - Int_rx_of | // abort condition 17.354 - Int_tx_empty | // write condition (writing needed) 17.355 - Int_tx_abort; // abort condition 17.356 - 17.357 - _regs[Tx_fifo_thold] = 0; // write when 0 in queue 17.358 - 17.359 - // Make sure that the stop condition does not occur automatically. 17.360 - 17.361 - _regs[Smb_control] = _regs[Smb_control] | Smb_no_stop_empty; 17.362 -} 17.363 - 17.364 - 17.365 - 17.366 -// Return whether the device is active. 17.367 - 17.368 -int 17.369 -I2c_jz4780_channel::active() 17.370 +: I2c_channel(start, clock, cpm, frequency) 17.371 { 17.372 - return _regs[Smb_status] & Smb_status_master_act; 17.373 -} 17.374 - 17.375 -// Return whether data is available to receive. 17.376 - 17.377 -int 17.378 -I2c_jz4780_channel::have_input() 17.379 -{ 17.380 - return _regs[Smb_status] & Smb_status_rx_nempty; 17.381 -} 17.382 - 17.383 -// Return whether data is queued for sending. 17.384 - 17.385 -int 17.386 -I2c_jz4780_channel::have_output() 17.387 -{ 17.388 - return !(_regs[Smb_status] & Smb_status_tx_empty); 17.389 -} 17.390 - 17.391 -// Return whether data can be queued for sending. 17.392 - 17.393 -int 17.394 -I2c_jz4780_channel::can_send() 17.395 -{ 17.396 - return _regs[Smb_status] & Smb_status_tx_nfull; 17.397 -} 17.398 - 17.399 -// Return whether a receive operation has failed. 17.400 - 17.401 -int 17.402 -I2c_jz4780_channel::read_failed() 17.403 -{ 17.404 - return _regs[Int_status] & Int_rx_of; 17.405 -} 17.406 - 17.407 -// Return whether a send operation has failed. 17.408 - 17.409 -int 17.410 -I2c_jz4780_channel::write_failed() 17.411 -{ 17.412 - return _regs[Int_status] & Int_tx_abort; 17.413 -} 17.414 - 17.415 -int 17.416 -I2c_jz4780_channel::read_done() 17.417 -{ 17.418 - return _pos == _total; 17.419 -} 17.420 - 17.421 -int 17.422 -I2c_jz4780_channel::write_done() 17.423 -{ 17.424 - return _reqpos == _total; 17.425 -} 17.426 - 17.427 -unsigned 17.428 -I2c_jz4780_channel::have_read() 17.429 -{ 17.430 - return _pos; 17.431 -} 17.432 - 17.433 -unsigned 17.434 -I2c_jz4780_channel::have_written() 17.435 -{ 17.436 - return _reqpos; 17.437 -} 17.438 - 17.439 -int 17.440 -I2c_jz4780_channel::failed() 17.441 -{ 17.442 - return _fail; 17.443 -} 17.444 - 17.445 - 17.446 - 17.447 -// Send read commands for empty queue entries. 17.448 - 17.449 -void 17.450 -I2c_jz4780_channel::queue_reads() 17.451 -{ 17.452 - unsigned int remaining = _total - _reqpos; 17.453 - unsigned int queued = _reqpos - _pos; 17.454 - 17.455 - // Permit one more issued read request due to the behaviour of the peripheral 17.456 - // to withhold a request unless the stop condition has been issued. 17.457 - 17.458 - unsigned int can_queue = Smb_fifo_limit - queued + 1; 17.459 - 17.460 - // Keep the number of reads in progress below the length of the read queue. 17.461 - 17.462 - if (!can_queue) 17.463 - return; 17.464 - 17.465 - // At most, only queue as many reads as are remaining. 17.466 - 17.467 - if (remaining < can_queue) 17.468 - can_queue = remaining; 17.469 - 17.470 - // Queue read requests for any remaining queue entries. 17.471 - 17.472 - while (can_queue && can_send()) 17.473 - { 17.474 - _regs[Smb_data_command] = Smb_command_read; 17.475 - _reqpos++; 17.476 - can_queue--; 17.477 - } 17.478 - 17.479 - // Issue the stop condition after the final read request. 17.480 - // In practice, an extra read request works better since it does not risk a 17.481 - // transmission abort condition and would permit following transactions. 17.482 - // However, it does risk causing an address autoincrement with some devices. 17.483 - 17.484 - if (_total == _reqpos) 17.485 - _regs[Smb_data_command] = Smb_command_read; 17.486 - //stop(); 17.487 - 17.488 - // Update the threshold to be notified of any reduced remaining amount. 17.489 - 17.490 - set_read_threshold(); 17.491 -} 17.492 - 17.493 -// Send write commands for empty queue entries. 17.494 - 17.495 -void 17.496 -I2c_jz4780_channel::queue_writes() 17.497 -{ 17.498 - unsigned int remaining = _total - _reqpos; 17.499 - unsigned int can_queue = Smb_fifo_limit; 17.500 - 17.501 - if (remaining < can_queue) 17.502 - can_queue = remaining; 17.503 - 17.504 - // Queue write requests for any remaining queue entries. 17.505 - 17.506 - while (can_queue && can_send()) 17.507 - { 17.508 - _regs[Smb_data_command] = Smb_command_write | _buf[_reqpos]; 17.509 - _reqpos++; 17.510 - can_queue--; 17.511 - } 17.512 -} 17.513 - 17.514 -// Store read command results from the queue. 17.515 - 17.516 -void 17.517 -I2c_jz4780_channel::store_reads() 17.518 -{ 17.519 - // Read any input and store it in the buffer. 17.520 - 17.521 - while (have_input() && (_pos < _reqpos)) 17.522 - { 17.523 - _buf[_pos] = _regs[Smb_data_command] & 0xff; 17.524 - _pos++; 17.525 - } 17.526 -} 17.527 - 17.528 -void 17.529 -I2c_jz4780_channel::set_read_threshold() 17.530 -{ 17.531 - unsigned int queued = _reqpos - _pos; 17.532 - 17.533 - if (!queued) 17.534 - return; 17.535 - 17.536 - // Read all expected. 17.537 - 17.538 - _regs[Rx_fifo_thold] = queued - 1; 17.539 -} 17.540 - 17.541 -// Read from the target device. 17.542 - 17.543 -void 17.544 -I2c_jz4780_channel::start_read(uint8_t buf[], unsigned int total) 17.545 -{ 17.546 - _buf = buf; 17.547 - _total = total; 17.548 - _pos = 0; 17.549 - _reqpos = 0; 17.550 - _fail = 0; 17.551 - 17.552 - set_read_threshold(); 17.553 -} 17.554 - 17.555 -void 17.556 -I2c_jz4780_channel::read() 17.557 -{ 17.558 - if (read_failed() || write_failed()) 17.559 - { 17.560 - _fail = 1; 17.561 - return; 17.562 - } 17.563 - 17.564 - if (_regs[Int_status] & Int_rx_full) 17.565 - store_reads(); 17.566 - if (_regs[Int_status] & Int_tx_empty) 17.567 - queue_reads(); 17.568 -} 17.569 - 17.570 -// Write to the target device. 17.571 - 17.572 -void 17.573 -I2c_jz4780_channel::start_write(uint8_t buf[], unsigned int total) 17.574 -{ 17.575 - _buf = buf; 17.576 - _total = total; 17.577 - _reqpos = 0; 17.578 - _fail = 0; 17.579 -} 17.580 - 17.581 -void 17.582 -I2c_jz4780_channel::write() 17.583 -{ 17.584 - if (write_failed()) 17.585 - { 17.586 - _fail = 1; 17.587 - return; 17.588 - } 17.589 - 17.590 - if (_regs[Int_status] & Int_tx_empty) 17.591 - queue_writes(); 17.592 -} 17.593 - 17.594 -// Explicitly stop communication. 17.595 - 17.596 -void 17.597 -I2c_jz4780_channel::stop() 17.598 -{ 17.599 - _regs[Smb_control] = _regs[Smb_control] & ~Smb_no_stop_empty; 17.600 } 17.601 17.602 17.603 @@ -616,27 +52,10 @@ 17.604 // Initialise the I2C controller. 17.605 17.606 I2c_jz4780_chip::I2c_jz4780_chip(l4_addr_t start, l4_addr_t end, 17.607 - Cpm_jz4780_chip *cpm, 17.608 + Cpm_chip *cpm, 17.609 uint32_t frequency) 17.610 -: _start(start), _end(end), _cpm(cpm), _frequency(frequency) 17.611 -{ 17.612 -} 17.613 - 17.614 -// Obtain a channel object. 17.615 - 17.616 -I2c_jz4780_channel * 17.617 -I2c_jz4780_chip::get_channel(uint8_t channel) 17.618 +: I2c_chip(start, end, cpm, frequency) 17.619 { 17.620 - l4_addr_t block = _start + channel * Smb_block_offset; 17.621 - enum Clock_identifiers bits[] = {Clock_i2c0, Clock_i2c1, Clock_i2c2, Clock_i2c3, Clock_i2c4}; 17.622 - 17.623 - if (channel < 5) 17.624 - { 17.625 - _cpm->start_clock(bits[channel]); 17.626 - return new I2c_jz4780_channel(block, _cpm, _frequency); 17.627 - } 17.628 - else 17.629 - throw -L4_EINVAL; 17.630 } 17.631 17.632 17.633 @@ -645,12 +64,7 @@ 17.634 17.635 void *jz4780_i2c_init(l4_addr_t start, l4_addr_t end, void *cpm, uint32_t frequency) 17.636 { 17.637 - return (void *) new I2c_jz4780_chip(start, end, static_cast<Cpm_jz4780_chip *>(cpm), frequency); 17.638 -} 17.639 - 17.640 -void jz4780_i2c_disable(void *i2c_channel) 17.641 -{ 17.642 - static_cast<I2c_jz4780_channel *>(i2c_channel)->disable(); 17.643 + return (void *) new I2c_jz4780_chip(start, end, static_cast<Cpm_chip *>(cpm), frequency); 17.644 } 17.645 17.646 void *jz4780_i2c_get_channel(void *i2c, uint8_t channel) 17.647 @@ -658,14 +72,20 @@ 17.648 return static_cast<I2c_jz4780_chip *>(i2c)->get_channel(channel); 17.649 } 17.650 17.651 +uint32_t jz4780_i2c_get_frequency(void *i2c_channel) 17.652 +{ 17.653 + return static_cast<I2c_jz4780_channel *>(i2c_channel)->get_frequency(); 17.654 +} 17.655 + 17.656 void jz4780_i2c_set_target(void *i2c_channel, uint8_t addr) 17.657 { 17.658 static_cast<I2c_jz4780_channel *>(i2c_channel)->set_target(addr); 17.659 } 17.660 17.661 -void jz4780_i2c_start_read(void *i2c_channel, uint8_t buf[], unsigned int total) 17.662 +void jz4780_i2c_start_read(void *i2c_channel, uint8_t buf[], unsigned int total, 17.663 + int stop) 17.664 { 17.665 - static_cast<I2c_jz4780_channel *>(i2c_channel)->start_read(buf, total); 17.666 + static_cast<I2c_jz4780_channel *>(i2c_channel)->start_read(buf, total, stop); 17.667 } 17.668 17.669 void jz4780_i2c_read(void *i2c_channel) 17.670 @@ -673,9 +93,10 @@ 17.671 static_cast<I2c_jz4780_channel *>(i2c_channel)->read(); 17.672 } 17.673 17.674 -void jz4780_i2c_start_write(void *i2c_channel, uint8_t buf[], unsigned int total) 17.675 +void jz4780_i2c_start_write(void *i2c_channel, uint8_t buf[], unsigned int total, 17.676 + int stop) 17.677 { 17.678 - static_cast<I2c_jz4780_channel *>(i2c_channel)->start_write(buf, total); 17.679 + static_cast<I2c_jz4780_channel *>(i2c_channel)->start_write(buf, total, stop); 17.680 } 17.681 17.682 void jz4780_i2c_write(void *i2c_channel) 17.683 @@ -707,8 +128,3 @@ 17.684 { 17.685 return static_cast<I2c_jz4780_channel *>(i2c_channel)->failed(); 17.686 } 17.687 - 17.688 -void jz4780_i2c_stop(void *i2c_channel) 17.689 -{ 17.690 - static_cast<I2c_jz4780_channel *>(i2c_channel)->stop(); 17.691 -}
18.1 --- a/pkg/devices/lib/i2c/src/x1600.cc Sat Oct 28 01:15:45 2023 +0200 18.2 +++ b/pkg/devices/lib/i2c/src/x1600.cc Sun Oct 29 16:14:38 2023 +0100 18.3 @@ -20,146 +20,6 @@ 18.4 */ 18.5 18.6 #include <l4/devices/i2c-x1600.h> 18.7 -#include <l4/devices/hw_mmio_register_block.h> 18.8 - 18.9 -#include <l4/sys/icu.h> 18.10 -#include <l4/util/util.h> 18.11 -#include <sys/time.h> 18.12 - 18.13 -/* NOTE: This peripheral is very similar to the JZ4780 with the registers 18.14 - renamed to I2C from SMB, with a few high speed registers added, and 18.15 - with I2C_SDAHD appearing at a different location. */ 18.16 - 18.17 -enum Regs 18.18 -{ 18.19 - I2c_control = 0x000, // I2C_CON 18.20 - I2c_target_address = 0x004, // I2C_TAR 18.21 - I2c_slave_address = 0x008, // I2C_SAR 18.22 - I2c_master_code = 0x00c, // I2C_HS_MADDR 18.23 - I2c_data_command = 0x010, // I2C_DC 18.24 - Std_high_count = 0x014, // I2C_SHCNT 18.25 - Std_low_count = 0x018, // I2C_SLCNT 18.26 - Fast_high_count = 0x01c, // I2C_FHCNT 18.27 - Fast_low_count = 0x020, // I2C_FLCNT 18.28 - High_high_count = 0x024, // I2C_HHCNT 18.29 - High_low_count = 0x028, // I2C_HLCNT 18.30 - Int_status = 0x02c, // I2C_INTST (read-only) 18.31 - Int_mask = 0x030, // I2C_INTM 18.32 - Int_raw_status = 0x034, // I2C_RINTST (read-only) 18.33 - Rx_fifo_thold = 0x038, // I2C_RXTL 18.34 - Tx_fifo_thold = 0x03c, // I2C_TXTL 18.35 - Int_combined_clear = 0x040, // I2C_CINT (read-only) 18.36 - Int_rx_uf_clear = 0x044, // I2C_CRXUF (read-only) 18.37 - Int_rx_of_clear = 0x048, // I2C_CRXOF (read-only) 18.38 - Int_tx_of_clear = 0x04c, // I2C_CTXOF (read-only) 18.39 - Int_rd_req_clear = 0x050, // I2C_CRXREQ (read-only) 18.40 - Int_tx_abort_clear = 0x054, // I2C_CTXABT (read-only) 18.41 - Int_rx_done_clear = 0x058, // I2C_CRXDN (read-only) 18.42 - Int_activity_clear = 0x05c, // I2C_CACT (read-only) 18.43 - Int_stop_clear = 0x060, // I2C_CSTP (read-only) 18.44 - Int_start_clear = 0x064, // I2C_CSTT (read-only) 18.45 - Int_call_clear = 0x068, // I2C_CGC (read-only) 18.46 - I2c_enable = 0x06c, // I2C_ENB 18.47 - I2c_status = 0x070, // I2C_ST (read-only) 18.48 - Tx_fifo_count = 0x074, // I2C_TXFLR (read-only) 18.49 - Rx_fifo_count = 0x078, // I2C_RXFLR (read-only) 18.50 - I2c_sda_hold_time = 0x07c, // I2C_SDAHD 18.51 - Trans_abort_status = 0x080, // I2C_ABTSRC (read-only) 18.52 - Slv_data_nack = 0x084, // I2CSDNACK 18.53 - I2c_dma_ctrl = 0x088, // I2C_DMACR 18.54 - I2c_trans_data_lvl = 0x08c, // I2C_DMATDLR 18.55 - I2c_recv_data_lvl = 0x090, // I2C_DMARDLR 18.56 - I2c_sda_setup_time = 0x094, // I2C_SDASU 18.57 - I2c_ack_call = 0x098, // I2C_ACKGC 18.58 - I2c_enable_status = 0x09c, // I2C_ENBST (read-only) 18.59 - I2c_spike_suppress = 0x0a0, // I2C_FSPKLEN 18.60 - 18.61 - I2c_block_offset = 0x1000 18.62 -}; 18.63 - 18.64 -enum I2c_control_bits : unsigned 18.65 -{ 18.66 - I2c_disable_slave = 0x40, // SLVDIS (slave disabled) 18.67 - I2c_enable_restart = 0x20, // RESTART 18.68 - I2c_master_10bit = 0x10, // MATP (read-only) 18.69 - I2c_slave_10bit = 0x08, // SATP 18.70 - I2c_speed_mode_mask = 0x06, // SPEED 18.71 - I2c_enable_master = 0x01, // MD (master enabled) 18.72 - I2c_speed_bit = 1, // SPD 18.73 -}; 18.74 - 18.75 -enum I2c_speed_mode_values : unsigned 18.76 -{ 18.77 - I2c_speed_standard = 1, 18.78 - I2c_speed_fast = 2, 18.79 - I2c_speed_high = 3, 18.80 -}; 18.81 - 18.82 -enum I2c_enable_bits : unsigned 18.83 -{ 18.84 - I2c_enable_enabled = 0x01, // I2CEN 18.85 -}; 18.86 - 18.87 -enum I2c_status_bits : unsigned 18.88 -{ 18.89 - I2c_status_master_act = 0x20, // MSTACT (master active) 18.90 - I2c_status_rx_nempty = 0x08, // RFNE (read queue not empty) 18.91 - I2c_status_tx_empty = 0x04, // TFE (write queue empty) 18.92 - I2c_status_tx_nfull = 0x02, // TFNF (write queue not full) 18.93 - I2c_status_active = 0x01, // ACT (device active as master or slave) 18.94 -}; 18.95 - 18.96 -enum I2c_target_bits : unsigned 18.97 -{ 18.98 - I2c_target_master_10bit = 0x1000, 18.99 - I2c_target_special = 0x0800, // SPECIAL: perform general call or start byte 18.100 - I2c_target_start_byte = 0x0400, // Special: start byte (1) or general call (0) 18.101 - I2c_target_10bits = 0x3ff, // Mask for 10-bit address 18.102 - I2c_target_7bits = 0x7f, // Mask for 7-bit address 18.103 -}; 18.104 - 18.105 -enum I2c_hold_control_bits : unsigned 18.106 -{ 18.107 - /* The hold enable flag has been removed since the JZ4780 and the hold time 18.108 - field widened. */ 18.109 - 18.110 - I2c_hold_mask = 0xffff, 18.111 -}; 18.112 - 18.113 -enum I2c_setup_control_bits : unsigned 18.114 -{ 18.115 - I2c_setup_mask = 0x0ff, // SDASU 18.116 -}; 18.117 - 18.118 -enum I2c_command_bits : unsigned 18.119 -{ 18.120 - I2c_command_restart = 0x400, // RESTART: explicit restart before next byte 18.121 - I2c_command_stop = 0x200, // STOP: explicit stop after next byte 18.122 - I2c_command_no_stop = 0x000, 18.123 - I2c_command_read = 0x100, // CMD 18.124 - I2c_command_write = 0x000, // CMD 18.125 -}; 18.126 - 18.127 -enum I2c_fifo_bits : unsigned 18.128 -{ 18.129 - I2c_fifo_limit = 64, // RXTL, TXTL (256 noted in field description) 18.130 -}; 18.131 - 18.132 -enum Int_bits : unsigned 18.133 -{ 18.134 - Int_call = 0x800, // IGC (general call received) 18.135 - Int_start = 0x400, // ISTT (start/restart condition occurred) 18.136 - Int_stop = 0x200, // ISTP (stop condition occurred) 18.137 - Int_activity = 0x100, // IACT (bus activity interrupt) 18.138 - Int_rx_done = 0x080, // RXDN (read from master device done) 18.139 - Int_tx_abort = 0x040, // TXABT (transmit abort) 18.140 - Int_rd_req = 0x020, // RDREQ (read request from master device) 18.141 - Int_tx_empty = 0x010, // TXEMP (threshold reached or passed) 18.142 - Int_tx_of = 0x008, // TXOF (overflow when writing to queue) 18.143 - Int_rx_full = 0x004, // RXFL (threshold reached or exceeded) 18.144 - Int_rx_of = 0x002, // RXOF (overflow from device) 18.145 - Int_rx_uf = 0x001, // RXUF (underflow when reading from queue) 18.146 -}; 18.147 18.148 18.149 18.150 @@ -167,508 +27,9 @@ 18.151 18.152 I2c_x1600_channel::I2c_x1600_channel(l4_addr_t start, 18.153 enum Clock_identifiers clock, 18.154 - Cpm_x1600_chip *cpm, 18.155 + Cpm_chip *cpm, 18.156 uint32_t frequency) 18.157 -: _cpm(cpm), _frequency(frequency) 18.158 -{ 18.159 - _regs = new Hw::Mmio_register_block<32>(start); 18.160 - _cpm->start_clock(clock); 18.161 -} 18.162 - 18.163 -// Enable the channel. 18.164 - 18.165 -void 18.166 -I2c_x1600_channel::enable() 18.167 -{ 18.168 - _regs[I2c_enable] = I2c_enable_enabled; 18.169 - while (!(_regs[I2c_enable_status] & I2c_enable_enabled)); 18.170 -} 18.171 - 18.172 -// Disable the channel. 18.173 - 18.174 -void 18.175 -I2c_x1600_channel::disable() 18.176 -{ 18.177 - _regs[I2c_enable] = 0; 18.178 - while (_regs[I2c_enable_status] & I2c_enable_enabled); 18.179 -} 18.180 - 18.181 -// Return the configured frequency. 18.182 - 18.183 -uint32_t 18.184 -I2c_x1600_channel::get_frequency() 18.185 -{ 18.186 - return _frequency; 18.187 -} 18.188 - 18.189 -// Set the frequency-related peripheral parameters. 18.190 - 18.191 -void 18.192 -I2c_x1600_channel::set_frequency() 18.193 -{ 18.194 - // The APB clock (PCLK) is used to drive I2C transfers. Its value must be 18.195 - // obtained from the CPM unit. It is known as I2C_DEV_CLK here and is scaled 18.196 - // to kHz in order to keep the numbers easily representable, as is the bus 18.197 - // frequency. 18.198 - 18.199 - uint32_t i2c_dev_clk = _cpm->get_frequency(Clock_pclock) / 1000; 18.200 - 18.201 - // Note that this is not I2C_DEV_CLK but the actual I2C bus frequency. 18.202 - 18.203 - uint32_t i2c_clk = _frequency / 1000; 18.204 - 18.205 - // Select the appropriate speed. 18.206 - 18.207 - unsigned int speed = (i2c_clk <= 100) ? I2c_speed_standard 18.208 - : (i2c_clk <= 400 ? I2c_speed_fast 18.209 - : I2c_speed_high); 18.210 - 18.211 - // NOTE: Permit broader configuration elsewhere. 18.212 - 18.213 - _regs[I2c_control] = (speed << I2c_speed_bit) | 18.214 - I2c_disable_slave | 18.215 - I2c_enable_restart | 18.216 - I2c_enable_master; 18.217 - 18.218 - // According to the programming manual, if the PCLK period is T{I2C_DEV_CLK} 18.219 - // then the I2C clock period is... 18.220 - 18.221 - // T{SCL} = T{SCL_high} + T{SCL_low} 18.222 - 18.223 - // Where... 18.224 - 18.225 - // T{SCL_low} = T{I2C_DEV_CLK} * (#cycles for low signal) 18.226 - // T{SCL_high} = T{I2C_DEV_CLK} * (#cycles for high signal) 18.227 - 18.228 - // Since, with minimum periods being defined... 18.229 - 18.230 - // T{SCL} >= T{min_SCL} 18.231 - // T{SCL_low} >= T{min_SCL_low} 18.232 - // T{SCL_high} >= T{min_SCL_high} 18.233 - // T{min_SCL} = T{min_SCL_low} + T{min_SCL_high} 18.234 - 18.235 - // Then the following applies... 18.236 - 18.237 - // T{I2C_DEV_CLK} * (#cycles for low signal)) >= T{min_SCL_low} 18.238 - // T{I2C_DEV_CLK} * (#cycles for high signal) >= T{min_SCL_high} 18.239 - 18.240 - // To work with different clock speeds while maintaining the low-to-high 18.241 - // ratios: 18.242 - 18.243 - // T{min_SCL_low} = T{min_SCL} * T{min_SCL_low} / T{min_SCL} 18.244 - // = T{min_SCL} * (T{min_SCL_low} / (T{min_SCL_low} + T{min_SCL_high})) 18.245 - 18.246 - // T{min_SCL_high} = T{min_SCL} * T{min_SCL_high} / T{min_SCL} 18.247 - // = T{min_SCL} * (T{min_SCL_high} / (T{min_SCL_low} + T{min_SCL_high})) 18.248 - 18.249 - // Constraints are given with respect to the high and low count registers. 18.250 - 18.251 - // #cycles for high signal = I2CxHCNT + 8 18.252 - // #cycles for low signal = I2CxLCNT + 1 18.253 - 18.254 - // From earlier, this yields... 18.255 - 18.256 - // T{I2C_DEV_CLK} * (I2CxLCNT + 1) >= T{min_SCL_low} 18.257 - // T{I2C_DEV_CLK} * (I2CxHCNT + 8) >= T{min_SCL_high} 18.258 - 18.259 - // Rearranging... 18.260 - 18.261 - // I2CxLCNT >= (T{min_SCL_low} / T{I2C_DEV_CLK}) - 1 18.262 - // >= T{min_SCL_low} * I2C_DEV_CLK - 1 18.263 - 18.264 - // I2CxHCNT >= (T{min_SCL_high} / T{I2C_DEV_CLK}) - 8 18.265 - // >= T{min_SCL_high} * I2C_DEV_CLK - 8 18.266 - 18.267 - // Introducing the definitions for the high and low periods... 18.268 - 18.269 - // I2CxLCNT >= T{min_SCL} * (T{min_SCL_low} / (T{min_SCL_low} + T{min_SCL_high})) * I2C_DEV_CLK - 1 18.270 - // >= (T{min_SCL_low} / T{min_SCL}) * I2C_DEV_CLK / I2C_BUS_CLK - 1 18.271 - 18.272 - // I2CxHCNT >= T{min_SCL} * (T{min_SCL_high} / (T{min_SCL_low} + T{min_SCL_high})) * I2C_DEV_CLK - 8 18.273 - // >= (T{min_SCL_high} / T{min_SCL}) * I2C_DEV_CLK / I2C_BUS_CLK - 8 18.274 - 18.275 - uint32_t high_reg, low_reg; 18.276 - uint32_t high_count, low_count; 18.277 - int32_t hold_count; 18.278 - uint32_t setup_count; 18.279 - 18.280 - // Level hold times: 18.281 - 18.282 - // Standard Fast High 18.283 - // SCL low 4.7us 1.3us 0.5us 18.284 - // SCL high 4.0us 0.6us 0.26us + 18.285 - // SCL period 8.7us 1.9us 0.76us = 18.286 - 18.287 - // See: UM10204 "I2C-bus specification and user manual" 18.288 - // Table 10: t{LOW} and t{HIGH} 18.289 - 18.290 - if (i2c_clk <= 100) // 100 kHz 18.291 - { 18.292 - low_count = (i2c_dev_clk * 47) / (i2c_clk * 87) - 1; 18.293 - high_count = (i2c_dev_clk * 40) / (i2c_clk * 87) - 8; 18.294 - low_reg = Std_low_count; 18.295 - high_reg = Std_high_count; 18.296 - } 18.297 - else if (i2c_clk <= 400) // 400 kHz 18.298 - { 18.299 - low_count = (i2c_dev_clk * 13) / (i2c_clk * 19) - 1; 18.300 - high_count = (i2c_dev_clk * 6) / (i2c_clk * 19) - 8; 18.301 - low_reg = Fast_low_count; 18.302 - high_reg = Fast_high_count; 18.303 - } 18.304 - else // > 400 kHz 18.305 - { 18.306 - // Note how the frequencies are scaled to accommodate the extra precision 18.307 - // required. 18.308 - 18.309 - low_count = (i2c_dev_clk / 10 * 50) / (i2c_clk / 10 * 76) - 1; 18.310 - high_count = (i2c_dev_clk / 10 * 26) / (i2c_clk / 10 * 76) - 8; 18.311 - low_reg = High_low_count; 18.312 - high_reg = High_high_count; 18.313 - } 18.314 - 18.315 - // Minimum counts are 8 and 6 for low and high respectively. 18.316 - 18.317 - _regs[low_reg] = low_count < 8 ? 8 : low_count; 18.318 - _regs[high_reg] = high_count < 6 ? 6 : high_count; 18.319 - 18.320 - // Data hold and setup times: 18.321 - 18.322 - // Standard Fast High 18.323 - // t{HD;DAT} 300ns 300ns 300ns 18.324 - // t{SU;DAT} 250ns 100ns 50ns 18.325 - 18.326 - // See: UM10204 "I2C-bus specification and user manual" 18.327 - // Table 10: t{HD;DAT} and t{SU;DAT}, also note [3] 18.328 - 18.329 - // T{delay} = (I2CSDAHD + 2) * T{I2C_DEV_CLK} 18.330 - // I2CSDAHD = T{delay} / T{I2C_DEV_CLK} - 2 18.331 - // I2CSDAHD = I2C_DEV_CLK * T{delay} - 2 18.332 - 18.333 - // Since the device clock is in kHz (scaled down by 1000) and the times are 18.334 - // given in ns (scaled up by 1000000000), a division of 1000000 is introduced. 18.335 - 18.336 - hold_count = (i2c_dev_clk * 300) / 1000000 - 1; 18.337 - 18.338 - _regs[I2c_sda_hold_time] = (_regs[I2c_sda_hold_time] & ~I2c_hold_mask) | 18.339 - (hold_count < 0 ? 0 18.340 - : (hold_count < (int) I2c_hold_mask ? (uint32_t) hold_count 18.341 - : I2c_hold_mask)); 18.342 - 18.343 - // I2C_SDASU is apparently not used in master mode. 18.344 - 18.345 - // T{delay} = (I2CSDASU - 1) * T{I2C_DEV_CLK} 18.346 - // I2CSDASU = T{delay} / T{I2C_DEV_CLK} + 1 18.347 - // I2CSDASU = I2C_DEV_CLK * T{delay} + 1 18.348 - 18.349 - if (i2c_clk <= 100) 18.350 - setup_count = (i2c_dev_clk * 250) / 1000000 + 1; 18.351 - else if (i2c_clk <= 400) 18.352 - setup_count = (i2c_dev_clk * 100) / 1000000 + 1; 18.353 - else 18.354 - setup_count = (i2c_dev_clk * 50) / 1000000 + 1; 18.355 - 18.356 - _regs[I2c_sda_setup_time] = (_regs[I2c_sda_setup_time] & ~I2c_setup_mask) | 18.357 - (setup_count < I2c_setup_mask ? setup_count : I2c_setup_mask); 18.358 -} 18.359 - 18.360 -// Set the target address and enable transfer. 18.361 -// NOTE: Only supporting 7-bit addresses currently. 18.362 - 18.363 -void 18.364 -I2c_x1600_channel::set_target(uint8_t address) 18.365 -{ 18.366 - disable(); 18.367 - set_frequency(); 18.368 - _regs[I2c_target_address] = address & I2c_target_7bits; 18.369 - init_parameters(); 18.370 - enable(); 18.371 -} 18.372 - 18.373 - 18.374 - 18.375 -// Reset interrupt flags upon certain conditions. 18.376 - 18.377 -void 18.378 -I2c_x1600_channel::reset_flags() 18.379 -{ 18.380 - volatile uint32_t r; 18.381 - 18.382 - _regs[Int_mask] = 0; 18.383 - 18.384 - // Read from the register to clear interrupts. 18.385 - 18.386 - r = _regs[Int_combined_clear]; 18.387 - (void) r; 18.388 -} 18.389 - 18.390 -// Initialise interrupt flags and queue thresholds for reading and writing. 18.391 - 18.392 -void 18.393 -I2c_x1600_channel::init_parameters() 18.394 -{ 18.395 - // Handle read queue conditions for data, write queue conditions for commands. 18.396 - 18.397 - reset_flags(); 18.398 - 18.399 - _regs[Tx_fifo_thold] = 0; // write when 0 in queue 18.400 -} 18.401 - 18.402 - 18.403 - 18.404 -// Return whether the device is active. 18.405 - 18.406 -int 18.407 -I2c_x1600_channel::active() 18.408 -{ 18.409 - return _regs[I2c_status] & I2c_status_master_act; 18.410 -} 18.411 - 18.412 -// Return whether data is available to receive. 18.413 - 18.414 -int 18.415 -I2c_x1600_channel::have_input() 18.416 -{ 18.417 - return _regs[I2c_status] & I2c_status_rx_nempty; 18.418 -} 18.419 - 18.420 -// Return whether data is queued for sending. 18.421 - 18.422 -int 18.423 -I2c_x1600_channel::have_output() 18.424 -{ 18.425 - return !(_regs[I2c_status] & I2c_status_tx_empty); 18.426 -} 18.427 - 18.428 -// Return whether data can be queued for sending. 18.429 - 18.430 -int 18.431 -I2c_x1600_channel::can_send() 18.432 -{ 18.433 - return _regs[I2c_status] & I2c_status_tx_nfull; 18.434 -} 18.435 - 18.436 -// Return whether a receive operation has failed. 18.437 - 18.438 -int 18.439 -I2c_x1600_channel::read_failed() 18.440 -{ 18.441 - return _regs[Int_status] & Int_rx_of; 18.442 -} 18.443 - 18.444 -// Return whether a send operation has failed. 18.445 - 18.446 -int 18.447 -I2c_x1600_channel::write_failed() 18.448 -{ 18.449 - return _regs[Int_status] & Int_tx_abort; 18.450 -} 18.451 - 18.452 -int 18.453 -I2c_x1600_channel::read_done() 18.454 -{ 18.455 - return _pos == _total; 18.456 -} 18.457 - 18.458 -int 18.459 -I2c_x1600_channel::write_done() 18.460 -{ 18.461 - return (_reqpos == _total) && !have_output(); 18.462 -} 18.463 - 18.464 -unsigned 18.465 -I2c_x1600_channel::have_read() 18.466 -{ 18.467 - return _pos; 18.468 -} 18.469 - 18.470 -unsigned 18.471 -I2c_x1600_channel::have_written() 18.472 -{ 18.473 - return _reqpos; 18.474 -} 18.475 - 18.476 -int 18.477 -I2c_x1600_channel::failed() 18.478 -{ 18.479 - return _fail; 18.480 -} 18.481 - 18.482 - 18.483 - 18.484 -// Send read commands for empty queue entries. 18.485 - 18.486 -void 18.487 -I2c_x1600_channel::queue_reads() 18.488 -{ 18.489 - unsigned int remaining = _total - _reqpos; 18.490 - unsigned int queued = _reqpos - _pos; 18.491 - unsigned int can_queue = I2c_fifo_limit - queued; 18.492 - 18.493 - // Keep the number of reads in progress below the length of the read queue. 18.494 - 18.495 - if (!can_queue) 18.496 - return; 18.497 - 18.498 - // At most, only queue as many reads as are remaining. 18.499 - 18.500 - if (remaining < can_queue) 18.501 - can_queue = remaining; 18.502 - 18.503 - // Queue read requests for any remaining queue entries. 18.504 - 18.505 - while (can_queue && can_send()) 18.506 - { 18.507 - uint32_t stop = _stop && (_reqpos == _total - 1) ? I2c_command_stop : I2c_command_no_stop; 18.508 - 18.509 - _regs[I2c_data_command] = I2c_command_read | stop; 18.510 - _reqpos++; 18.511 - can_queue--; 18.512 - } 18.513 - 18.514 - // Update the threshold to be notified of any reduced remaining amount. 18.515 - 18.516 - set_read_threshold(); 18.517 -} 18.518 - 18.519 -// Send write commands for empty queue entries. 18.520 - 18.521 -void 18.522 -I2c_x1600_channel::queue_writes() 18.523 -{ 18.524 - unsigned int remaining = _total - _reqpos; 18.525 - unsigned int can_queue = I2c_fifo_limit; 18.526 - 18.527 - if (remaining < can_queue) 18.528 - can_queue = remaining; 18.529 - 18.530 - // Queue write requests for any remaining queue entries. 18.531 - 18.532 - while (can_queue && can_send()) 18.533 - { 18.534 - uint32_t stop = _stop && (_reqpos == _total - 1) ? I2c_command_stop : I2c_command_no_stop; 18.535 - 18.536 - _regs[I2c_data_command] = I2c_command_write | _buf[_reqpos] | stop; 18.537 - _reqpos++; 18.538 - can_queue--; 18.539 - } 18.540 -} 18.541 - 18.542 -// Store read command results from the queue. 18.543 - 18.544 -void 18.545 -I2c_x1600_channel::store_reads() 18.546 -{ 18.547 - // Read any input and store it in the buffer. 18.548 - 18.549 - while (have_input() && (_pos < _reqpos)) 18.550 - { 18.551 - _buf[_pos] = _regs[I2c_data_command] & 0xff; 18.552 - _pos++; 18.553 - } 18.554 -} 18.555 - 18.556 -void 18.557 -I2c_x1600_channel::set_read_threshold() 18.558 -{ 18.559 - unsigned int queued = _reqpos - _pos; 18.560 - 18.561 - if (!queued) 18.562 - return; 18.563 - 18.564 - // Read all expected. 18.565 - 18.566 - _regs[Rx_fifo_thold] = queued - 1; 18.567 -} 18.568 - 18.569 -// Read from the target device. 18.570 - 18.571 -void 18.572 -I2c_x1600_channel::start_read(uint8_t buf[], unsigned int total, int stop) 18.573 -{ 18.574 - _buf = buf; 18.575 - _total = total; 18.576 - _pos = 0; 18.577 - _reqpos = 0; 18.578 - _fail = 0; 18.579 - _stop = stop; 18.580 - 18.581 - reset_flags(); 18.582 - 18.583 - _regs[Int_mask] = Int_rx_full | // read condition (reading needed) 18.584 - Int_rx_of | // abort condition 18.585 - Int_tx_abort; // general abort condition 18.586 - 18.587 - // Perform initial read requests. 18.588 - 18.589 - read(); 18.590 -} 18.591 - 18.592 -void 18.593 -I2c_x1600_channel::read() 18.594 -{ 18.595 - // Test for the general transfer abort condition. 18.596 - 18.597 - if (read_failed() || write_failed()) 18.598 - { 18.599 - _fail = 1; 18.600 - _regs[Int_mask] = 0; 18.601 - disable(); 18.602 - enable(); 18.603 - return; 18.604 - } 18.605 - 18.606 - if (_regs[Int_status] & Int_rx_full) 18.607 - store_reads(); 18.608 - 18.609 - // Always attempt to queue more read requests. 18.610 - 18.611 - queue_reads(); 18.612 -} 18.613 - 18.614 -// Write to the target device. 18.615 - 18.616 -void 18.617 -I2c_x1600_channel::start_write(uint8_t buf[], unsigned int total, int stop) 18.618 -{ 18.619 - _buf = buf; 18.620 - _total = total; 18.621 - _reqpos = 0; 18.622 - _fail = 0; 18.623 - _stop = stop; 18.624 - 18.625 - reset_flags(); 18.626 - 18.627 - // Enable interrupts for further writes. 18.628 - 18.629 - _regs[Int_mask] = Int_tx_empty | // write condition (writing needed) 18.630 - Int_tx_abort; // abort condition 18.631 - 18.632 - // Perform initial writes. 18.633 - 18.634 - write(); 18.635 -} 18.636 - 18.637 -void 18.638 -I2c_x1600_channel::write() 18.639 -{ 18.640 - if (write_failed()) 18.641 - { 18.642 - _fail = 1; 18.643 - _regs[Int_mask] = 0; 18.644 - disable(); 18.645 - enable(); 18.646 - return; 18.647 - } 18.648 - 18.649 - if (_regs[Int_status] & Int_tx_empty) 18.650 - queue_writes(); 18.651 -} 18.652 - 18.653 -// Explicitly stop communication. 18.654 - 18.655 -void 18.656 -I2c_x1600_channel::stop() 18.657 +: I2c_channel(start, clock, cpm, frequency) 18.658 { 18.659 } 18.660 18.661 @@ -677,33 +38,19 @@ 18.662 // Initialise the I2C controller. 18.663 18.664 I2c_x1600_chip::I2c_x1600_chip(l4_addr_t start, l4_addr_t end, 18.665 - Cpm_x1600_chip *cpm, 18.666 - uint32_t frequency) 18.667 -: _start(start), _end(end), _cpm(cpm), _frequency(frequency) 18.668 + Cpm_chip *cpm, 18.669 + uint32_t frequency) 18.670 +: I2c_chip(start, end, cpm, frequency) 18.671 { 18.672 } 18.673 18.674 -// Obtain a channel object. 18.675 - 18.676 -I2c_x1600_channel * 18.677 -I2c_x1600_chip::get_channel(uint8_t channel) 18.678 -{ 18.679 - l4_addr_t block = _start + channel * I2c_block_offset; 18.680 - enum Clock_identifiers clocks[] = {Clock_i2c0, Clock_i2c1}; 18.681 - 18.682 - if (channel < 2) 18.683 - return new I2c_x1600_channel(block, clocks[channel], _cpm, _frequency); 18.684 - else 18.685 - throw -L4_EINVAL; 18.686 -} 18.687 - 18.688 18.689 18.690 // C language interface functions. 18.691 18.692 void *x1600_i2c_init(l4_addr_t start, l4_addr_t end, void *cpm, uint32_t frequency) 18.693 { 18.694 - return (void *) new I2c_x1600_chip(start, end, static_cast<Cpm_x1600_chip *>(cpm), frequency); 18.695 + return (void *) new I2c_x1600_chip(start, end, static_cast<Cpm_chip *>(cpm), frequency); 18.696 } 18.697 18.698 void *x1600_i2c_get_channel(void *i2c, uint8_t channel)
19.1 --- a/pkg/landfall-examples/ci20_i2c/ci20_i2c.c Sat Oct 28 01:15:45 2023 +0200 19.2 +++ b/pkg/landfall-examples/ci20_i2c/ci20_i2c.c Sun Oct 29 16:14:38 2023 +0100 19.3 @@ -63,19 +63,18 @@ 19.4 } 19.5 19.6 static long i2c_read(void *i2c_channel, uint8_t *buf, unsigned length, 19.7 - l4_cap_idx_t irqcap) 19.8 + int stop, l4_cap_idx_t irqcap) 19.9 { 19.10 l4_msgtag_t tag; 19.11 - long err; 19.12 19.13 - jz4780_i2c_start_read(i2c_channel, buf, length); 19.14 + jz4780_i2c_start_read(i2c_channel, buf, length, stop); 19.15 19.16 while (!jz4780_i2c_read_done(i2c_channel)) 19.17 { 19.18 - tag = l4_irq_receive(irqcap, l4_timeout(L4_IPC_TIMEOUT_NEVER, l4_timeout_rel(1, 20))); 19.19 + tag = l4_irq_receive(irqcap, l4_timeout(L4_IPC_TIMEOUT_NEVER, l4_timeout_from_us(1000))); 19.20 19.21 - if ((err = l4_ipc_error(tag, l4_utcb()))) 19.22 - return err; 19.23 + if (l4_ipc_error(tag, l4_utcb())) 19.24 + return 0; 19.25 19.26 if (jz4780_i2c_failed(i2c_channel)) 19.27 return 0; 19.28 @@ -87,19 +86,19 @@ 19.29 } 19.30 19.31 static long i2c_write(void *i2c_channel, uint8_t *buf, unsigned length, 19.32 - l4_cap_idx_t irqcap) 19.33 + int stop, l4_cap_idx_t irqcap) 19.34 { 19.35 l4_msgtag_t tag; 19.36 long err; 19.37 19.38 - jz4780_i2c_start_write(i2c_channel, buf, length); 19.39 + jz4780_i2c_start_write(i2c_channel, buf, length, stop); 19.40 19.41 while (!jz4780_i2c_write_done(i2c_channel)) 19.42 { 19.43 - tag = l4_irq_receive(irqcap, l4_timeout(L4_IPC_TIMEOUT_NEVER, l4_timeout_rel(1, 20))); 19.44 + tag = l4_irq_receive(irqcap, l4_timeout(L4_IPC_TIMEOUT_NEVER, l4_timeout_from_us(1000))); 19.45 19.46 if ((err = l4_ipc_error(tag, l4_utcb()))) 19.47 - return err; 19.48 + return 0; 19.49 19.50 if (jz4780_i2c_failed(i2c_channel)) 19.51 return 0; 19.52 @@ -115,9 +114,7 @@ 19.53 long pos; 19.54 19.55 memset(buffer, 0, length); 19.56 - pos = i2c_read(i2c_channel, buffer, length, irqcap); 19.57 - 19.58 - jz4780_i2c_stop(i2c_channel); 19.59 + pos = i2c_read(i2c_channel, buffer, length, 1, irqcap); 19.60 19.61 return pos; 19.62 } 19.63 @@ -125,7 +122,7 @@ 19.64 static long i2c_get_reg(void *i2c_channel, uint8_t reg, uint8_t *buffer, long length, l4_cap_idx_t irqcap) 19.65 { 19.66 buffer[0] = reg; 19.67 - i2c_write(i2c_channel, buffer, 1, irqcap); 19.68 + i2c_write(i2c_channel, buffer, 1, 0, irqcap); 19.69 19.70 return i2c_get(i2c_channel, buffer, length, irqcap); 19.71 } 19.72 @@ -137,9 +134,7 @@ 19.73 19.74 buf[0] = reg; 19.75 memcpy(buf + 1, buffer, length); 19.76 - pos = i2c_write(i2c_channel, buf, length + 1, irqcap); 19.77 - 19.78 - jz4780_i2c_stop(i2c_channel); 19.79 + pos = i2c_write(i2c_channel, buf, length + 1, 1, irqcap); 19.80 19.81 return pos; 19.82 } 19.83 @@ -459,8 +454,8 @@ 19.84 sleep(1); 19.85 } 19.86 19.87 - jz4780_i2c_disable(i2c0); 19.88 - jz4780_i2c_disable(i2c4); 19.89 + //jz4780_i2c_disable(i2c0); 19.90 + //jz4780_i2c_disable(i2c4); 19.91 19.92 /* Detach from the interrupt. */ 19.93